Skip to content
Merged
2 changes: 1 addition & 1 deletion src/simtools/applications/simulate_prod.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
Zenith angle in degrees.
nshow (int, optional)
Number of showers to simulate.
The Number of simulated events depends on the number of times a shower is re-used in the
The Number of simulated events depends on the number of times a shower is reused in the
telescope simulation. The number provided here is before any reuse factors.
start_run (int, required)
Start run number such that the actual run number will be 'start_run' + 'run'.
Expand Down
2 changes: 1 addition & 1 deletion src/simtools/corsika/corsika_histograms.py
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ def individual_telescopes(self, new_individual_telescopes: bool):
----------
new_individual_telescopes: bool
if False, the histograms are supposed to be filled for all telescopes.
if True, one histogram is set for each telescope sepparately.
if True, one histogram is set for each telescope separately.
"""
if new_individual_telescopes is None:
self._individual_telescopes = False
Expand Down
10 changes: 10 additions & 0 deletions src/simtools/schemas/integration_tests_config.metaschema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ definitions:
description: |
"Reference file used for comparison."
type: string
TEST_SIMTEL_CFG_FILES:
description: |
"Reference file used for comparison of sim_telarray configuration files."
type: object
additionalProperties: false
patternProperties:
"^[0-9]+\\.[0-9]+\\.[0-9]+$": # Semantic versioning pattern (e.g., "5.0.0", "6.0.0")
type: string
description: Path to the configuration file for the given version.
minProperties: 1
TOLERANCE:
description: "Allowed tolerance for floating point comparison."
type: number
Expand Down
121 changes: 101 additions & 20 deletions src/simtools/testing/validate_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@ def validate_all_tests(config, request, config_file_model_version):
elif config_file_model_version is not None:
_from_command_line = request.config.getoption("--model_version")
_from_config_file = config_file_model_version
if _from_command_line == _from_config_file:
validate_application_output(config)
validate_application_output(config, _from_command_line, _from_config_file)


def validate_application_output(config):
def validate_application_output(config, from_command_line=None, from_config_file=None):
"""
Validate application output against expected output.

Expand All @@ -45,31 +44,50 @@ def validate_application_output(config):
----------
config: dict
dictionary with the configuration for the application test.
from_command_line: str
Model version from the command line.
from_config_file: str
Model version from the configuration file.

"""
if "INTEGRATION_TESTS" not in config:
return

for integration_test in config["INTEGRATION_TESTS"]:
_logger.info(f"Testing application output: {integration_test}")
if "REFERENCE_OUTPUT_FILE" in integration_test:
_validate_reference_output_file(config, integration_test)

if "TEST_OUTPUT_FILES" in integration_test:
_validate_output_path_and_file(config, integration_test["TEST_OUTPUT_FILES"])
if "OUTPUT_FILE" in integration_test:
_validate_output_path_and_file(
config,
[{"PATH_DESCRIPTOR": "OUTPUT_PATH", "FILE": integration_test["OUTPUT_FILE"]}],
)

if "FILE_TYPE" in integration_test:
assert assertions.assert_file_type(
integration_test["FILE_TYPE"],
Path(config["CONFIGURATION"]["OUTPUT_PATH"]).joinpath(
config["CONFIGURATION"]["OUTPUT_FILE"]
),
)
if from_command_line == from_config_file:
if "REFERENCE_OUTPUT_FILE" in integration_test:
_validate_reference_output_file(config, integration_test)

if "TEST_OUTPUT_FILES" in integration_test:
_validate_output_path_and_file(config, integration_test["TEST_OUTPUT_FILES"])

if "OUTPUT_FILE" in integration_test:
_validate_output_path_and_file(
config,
[{"PATH_DESCRIPTOR": "OUTPUT_PATH", "FILE": integration_test["OUTPUT_FILE"]}],
)

if "FILE_TYPE" in integration_test:
assert assertions.assert_file_type(
integration_test["FILE_TYPE"],
Path(config["CONFIGURATION"]["OUTPUT_PATH"]).joinpath(
config["CONFIGURATION"]["OUTPUT_FILE"]
),
)
_test_simtel_cfg_files(config, integration_test, from_command_line, from_config_file)


def _test_simtel_cfg_files(config, integration_test, from_command_line, from_config_file):
"""Test simtel cfg files."""
if "TEST_SIMTEL_CFG_FILES" in integration_test:
if from_command_line:
test_simtel_cfg_file = integration_test["TEST_SIMTEL_CFG_FILES"].get(from_command_line)
else:
test_simtel_cfg_file = integration_test["TEST_SIMTEL_CFG_FILES"].get(from_config_file)
if test_simtel_cfg_file:
_validate_simtel_cfg_files(config, test_simtel_cfg_file)


def _validate_reference_output_file(config, integration_test):
Expand Down Expand Up @@ -238,3 +256,66 @@ def generate_mask(table, column, condition):
return False

return True


def _validate_simtel_cfg_files(config, simtel_cfg_file):
"""
Check sim_telarray configuration files and compare with reference file.

Note the finetuned naming of configuration files by simtools.

"""
reference_file = Path(simtel_cfg_file)
test_file = Path(config["CONFIGURATION"]["OUTPUT_PATH"]) / reference_file.name.replace(
"_test", f"_{config['CONFIGURATION']['LABEL']}"
)
_logger.info(
f"Comparing simtel cfg files: {reference_file} and {test_file} "
f"for model version {config['CONFIGURATION']['MODEL_VERSION']}"
)
return _compare_simtel_cfg_files(reference_file, test_file)


def _compare_simtel_cfg_files(reference_file, test_file):
"""
Compare two sim_telarray configuration files.

Line-by-line string comparison. Requires similar sequence of
parameters in the files. Ignore lines containing 'config_release'
(as it contains the simtools package version).

Parameters
----------
reference_file: Path
Reference sim_telarray configuration file.
test_file: Path
Test sim_telarray configuration file.

Returns
-------
bool
True if the files are equal.

"""
with open(reference_file, encoding="utf-8") as f1, open(test_file, encoding="utf-8") as f2:
reference_cfg = [line.rstrip() for line in f1 if line.strip()]
test_cfg = [line.rstrip() for line in f2 if line.strip()]

if len(reference_cfg) != len(test_cfg):
_logger.error(
f"Line counts differ: {reference_file} ({len(reference_cfg)} lines), "
f"{test_file} ({len(test_cfg)} lines)."
)
return False

for ref_line, test_line in zip(reference_cfg, test_cfg):
if any(ignore in ref_line for ignore in ("config_release", "Label")):
continue
if ref_line != test_line:
_logger.error(
f"Configuration files {reference_file} and {test_file} do not match: "
f"'{ref_line}' and '{test_line}'"
)
return False

return True
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,15 @@ CTA_SIMPIPE:
# The mean number of photons per telescope after atmospheric absorption and QE
# should be between 90 and 1000 (very loose requirement)
photons: [90, 1000]
- TEST_SIMTEL_CFG_FILES:
5.0.0: tests/resources/sim_telarray_configurations/CTA-North-LSTN-01-5.0.0_test.cfg
6.0.0: tests/resources/sim_telarray_configurations/CTA-North-LSTN-01-6.0.0_test.cfg
- TEST_SIMTEL_CFG_FILES:
5.0.0: tests/resources/sim_telarray_configurations/CTA-North-LSTN-02-5.0.0_test.cfg
6.0.0: tests/resources/sim_telarray_configurations/CTA-North-LSTN-02-6.0.0_test.cfg
- TEST_SIMTEL_CFG_FILES:
5.0.0: tests/resources/sim_telarray_configurations/CTA-North-MSTN-01-5.0.0_test.cfg
6.0.0: tests/resources/sim_telarray_configurations/CTA-North-MSTN-01-6.0.0_test.cfg
- TEST_SIMTEL_CFG_FILES:
5.0.0: tests/resources/sim_telarray_configurations/CTA-alpha-North-5.0.0_test.cfg
6.0.0: tests/resources/sim_telarray_configurations/CTA-alpha-North-6.0.0_test.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ CTA_SIMPIPE:
LABEL: check_output
MODEL_VERSION: 6.0.0
SITE: South
ARRAY_LAYOUT_NAME: alpha
ARRAY_LAYOUT_NAME: beta
PRIMARY: gamma
RUN_NUMBER_START: 1
NUMBER_OF_RUNS: 1
Expand All @@ -24,9 +24,9 @@ CTA_SIMPIPE:
INTEGRATION_TESTS:
- TEST_OUTPUT_FILES:
- PATH_DESCRIPTOR: PACK_FOR_GRID_REGISTER
FILE: run000001_gamma_za40deg_azm180deg_South_alpha_check_output.log_hist.tar.gz
FILE: run000001_gamma_za40deg_azm180deg_South_beta_check_output.log_hist.tar.gz
- PATH_DESCRIPTOR: PACK_FOR_GRID_REGISTER
FILE: run000001_gamma_za40deg_azm180deg_South_alpha_check_output.zst
FILE: run000001_gamma_za40deg_azm180deg_South_beta_check_output.zst
EXPECTED_OUTPUT:
# The mean trigger time for all telescopes should be
# between 0 and 50 ns (very loose requirement)
Expand All @@ -37,3 +37,15 @@ CTA_SIMPIPE:
# The mean number of photons per telescope after atmospheric absorption and QE
# should be between 90 and 1000 (very loose requirement)
photons: [90, 1000]
- TEST_SIMTEL_CFG_FILES:
5.0.0: tests/resources/sim_telarray_configurations/CTA-South-LSTS-01-5.0.0_test.cfg
6.0.0: tests/resources/sim_telarray_configurations/CTA-South-LSTS-01-6.0.0_test.cfg
- TEST_SIMTEL_CFG_FILES:
5.0.0: tests/resources/sim_telarray_configurations/CTA-South-MSTS-01-5.0.0_test.cfg
6.0.0: tests/resources/sim_telarray_configurations/CTA-South-MSTS-01-6.0.0_test.cfg
- TEST_SIMTEL_CFG_FILES:
5.0.0: tests/resources/sim_telarray_configurations/CTA-South-SSTS-01-5.0.0_test.cfg
6.0.0: tests/resources/sim_telarray_configurations/CTA-South-SSTS-01-6.0.0_test.cfg
- TEST_SIMTEL_CFG_FILES:
5.0.0: tests/resources/sim_telarray_configurations/CTA-beta-South-5.0.0_test.cfg
6.0.0: tests/resources/sim_telarray_configurations/CTA-beta-South-6.0.0_test.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
%==================================================
% TELESCOPE CONFIGURATION FILE
% Site: North
% ModelVersion: 5.0.0
% TelescopeModelName: LSTN-01
% Label: check_output
%==================================================
%
#ifdef TELESCOPE
echo Configuration for LSTN-01 - TELESCOPE $(TELESCOPE)
#endif

altitude = 2158.0
asum_clipping = 9999.0
asum_offset = 0.0
asum_shaping_file = none
asum_threshold = 270.0
atmospheric_transmission = atm_trans_2158_1_3_2_0_0_0.1_0.1.dat
axes_offsets = 0.0 0.0
camera_body_diameter = 348.0
camera_body_shape = 2
camera_config_file = camera_CTA-LST-1_analogsum21_v2020-04-14.dat
camera_degraded_efficiency = 1.0
camera_degraded_map = none
camera_depth = 0.0
camera_filter = transmission_lst_window_No7-10_ave.dat
camera_pixels = 1855
camera_transmission = 1.0
channels_per_chip = 4
default_trigger = AnalogSum
disc_ac_coupled = 1
disc_bins = 68
disc_start = 3
discriminator_amplitude = 6.5
discriminator_fall_time = 1.0
discriminator_gate_length = 2.0
discriminator_hysteresis = 0.0
discriminator_output_amplitude = 42.0
discriminator_output_var_percent = 10.0
discriminator_pulse_shape = pulse_LST_8dynode_pix6_20200204.dat
discriminator_rise_time = 1.0
discriminator_scale_threshold = 1.0
discriminator_sigsum_over_threshold = 0.0
discriminator_threshold = 99999.0
discriminator_time_over_threshold = 1.5
discriminator_var_gate_length = 0.1
discriminator_var_sigsum_over_threshold = 0.0
discriminator_var_threshold = 0.2
discriminator_var_time_over_threshold = 0.1
dish_shape_length = 2800.0
effective_focal_length = 2930.57 0.0 0.0 0.0 0.0
fadc_ac_coupled = 1
fadc_amplitude = 25.0
fadc_bins = 75
fadc_compensate_pedestal = -1
fadc_err_compensate_pedestal = 0.0
fadc_err_pedestal = 0.5
fadc_lg_amplitude = 1.28
fadc_lg_compensate_pedestal = -1
fadc_lg_err_compensate_pedestal = -1.0
fadc_lg_err_pedestal = 0.3
fadc_lg_max_signal = 4288
fadc_lg_noise = 5.7
fadc_lg_pedestal = 400.0
fadc_lg_sensitivity = -1.0
fadc_lg_sysvar_pedestal = -1.0
fadc_lg_var_pedestal = 0.4
fadc_lg_var_sensitivity = -1.0
fadc_max_signal = 4249
fadc_max_sum = 16777215
fadc_mhz = 1024.0
fadc_noise = 6.7
fadc_pedestal = 400.0
fadc_pulse_shape = pulse_LST_8dynode_pix6_20200204.dat
fadc_sensitivity = 1.0
fadc_sum_bins = 40
fadc_sum_offset = 9
fadc_sysvar_pedestal = 0.04
fadc_var_pedestal = 0.4
fadc_var_sensitivity = 0.01416
flatfielding = 1
focal_length = 2800.0
focus_offset = 6.55 0.0 0.0 0.0
gain_variation = 0.0187
hg_lg_variation = 0.0
mirror_align_random_distance = 0.0
mirror_align_random_horizontal = 0.0039 28.0 0.0 0.0
mirror_align_random_vertical = 0.0039 28.0 0.0 0.0
mirror_class = 0
mirror_degraded_reflection = 1.0
mirror_focal_length = 0.0
mirror_list = mirror_CTA-N-LST1_v2019-03-31.dat
mirror_offset = 93.25
mirror_reflection_random_angle = 0.0075 0.125 0.037
mirror_reflectivity = ref_LST_2020-04-23.dat
multiplicity_offset = -0.5
nightsky_background = all: 0.238006
nsb_autoscale_airmass = 0.84 0.29
nsb_offaxis = 0.0 0.0 0.0 0.0 0.0
num_gains = 2
only_triggered_telescopes = 1
parabolic_dish = 1
photon_delay = 19.0
pixeltrg_time_step = 0.0
pm_average_gain = 40000.0
pm_collection_efficiency = 1.0
pm_gain_index = 4.5
pm_photoelectron_spectrum = spe_LST_2020-05-09_AP2.0e-4.dat
pm_transit_time = 24.74 9.0 350.0 1066.0
pm_voltage_variation = 0.041
qe_variation = 0.03
quantum_efficiency = qe_lst1_20200318_high+low.dat
random_focal_length = 0.0 0.0
telescope_random_angle = 0.0
telescope_random_error = 0.0
telescope_transmission = 0.969 0.0 0.0 0.0 0.0 0.0
teltrig_min_sigsum = 7.8
teltrig_min_time = 0.5
transit_time_calib_error = 0.0
transit_time_compensate_error = 0.0
transit_time_compensate_step = 0.0
transit_time_error = 0.0
transit_time_jitter = 0.7
trigger_current_limit = 20.0
trigger_delay_compensation = 0.0 0.0 0.0 0.0
trigger_pixels = 3
iobuf_maximum = 1000000000
iobuf_output_maximum = 400000000
min_photoelectrons = 25
min_photons = 300
random_generator = mt19937
sampled_output = 1
save_pe_with_amplitude = 1
store_photoelectrons = 20
tailcut_scale = 2.6
config_release = 5.0.0 written by simtools v0.9.1.dev5+g763c36164
config_version = 5.0.0
camera_config_name = LSTN-01
camera_config_variant =
camera_config_version = 5.0.0
optics_config_name = LSTN-01
optics_config_variant =
optics_config_version = 5.0.0
Loading