Skip to content

Commit 02412a5

Browse files
authored
Merge pull request #1322 from gammasim/test-simtel-cfg-files
Allow for validation of simtools-generated configuration files for sim_telarray with reference files.
2 parents bb54697 + 7db2747 commit 02412a5

27 files changed

Lines changed: 3446 additions & 42 deletions

src/simtools/applications/simulate_prod.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
Zenith angle in degrees.
3232
nshow (int, optional)
3333
Number of showers to simulate.
34-
The Number of simulated events depends on the number of times a shower is re-used in the
34+
The Number of simulated events depends on the number of times a shower is reused in the
3535
telescope simulation. The number provided here is before any reuse factors.
3636
start_run (int, required)
3737
Start run number such that the actual run number will be 'start_run' + 'run'.

src/simtools/corsika/corsika_histograms.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ def individual_telescopes(self, new_individual_telescopes: bool):
678678
----------
679679
new_individual_telescopes: bool
680680
if False, the histograms are supposed to be filled for all telescopes.
681-
if True, one histogram is set for each telescope sepparately.
681+
if True, one histogram is set for each telescope separately.
682682
"""
683683
if new_individual_telescopes is None:
684684
self._individual_telescopes = False

src/simtools/schemas/integration_tests_config.metaschema.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ definitions:
8282
description: |
8383
"Reference file used for comparison."
8484
type: string
85+
TEST_SIMTEL_CFG_FILES:
86+
description: |
87+
"Reference file used for comparison of sim_telarray configuration files."
88+
type: object
89+
additionalProperties: false
90+
patternProperties:
91+
"^[0-9]+\\.[0-9]+\\.[0-9]+$": # Semantic versioning pattern (e.g., "5.0.0", "6.0.0")
92+
type: string
93+
description: Path to the configuration file for the given version.
94+
minProperties: 1
8595
TOLERANCE:
8696
description: "Allowed tolerance for floating point comparison."
8797
type: number

src/simtools/testing/validate_output.py

Lines changed: 101 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,10 @@ def validate_all_tests(config, request, config_file_model_version):
3131
elif config_file_model_version is not None:
3232
_from_command_line = request.config.getoption("--model_version")
3333
_from_config_file = config_file_model_version
34-
if _from_command_line == _from_config_file:
35-
validate_application_output(config)
34+
validate_application_output(config, _from_command_line, _from_config_file)
3635

3736

38-
def validate_application_output(config):
37+
def validate_application_output(config, from_command_line=None, from_config_file=None):
3938
"""
4039
Validate application output against expected output.
4140
@@ -45,31 +44,50 @@ def validate_application_output(config):
4544
----------
4645
config: dict
4746
dictionary with the configuration for the application test.
47+
from_command_line: str
48+
Model version from the command line.
49+
from_config_file: str
50+
Model version from the configuration file.
4851
4952
"""
5053
if "INTEGRATION_TESTS" not in config:
5154
return
5255

5356
for integration_test in config["INTEGRATION_TESTS"]:
5457
_logger.info(f"Testing application output: {integration_test}")
55-
if "REFERENCE_OUTPUT_FILE" in integration_test:
56-
_validate_reference_output_file(config, integration_test)
57-
58-
if "TEST_OUTPUT_FILES" in integration_test:
59-
_validate_output_path_and_file(config, integration_test["TEST_OUTPUT_FILES"])
60-
if "OUTPUT_FILE" in integration_test:
61-
_validate_output_path_and_file(
62-
config,
63-
[{"PATH_DESCRIPTOR": "OUTPUT_PATH", "FILE": integration_test["OUTPUT_FILE"]}],
64-
)
6558

66-
if "FILE_TYPE" in integration_test:
67-
assert assertions.assert_file_type(
68-
integration_test["FILE_TYPE"],
69-
Path(config["CONFIGURATION"]["OUTPUT_PATH"]).joinpath(
70-
config["CONFIGURATION"]["OUTPUT_FILE"]
71-
),
72-
)
59+
if from_command_line == from_config_file:
60+
if "REFERENCE_OUTPUT_FILE" in integration_test:
61+
_validate_reference_output_file(config, integration_test)
62+
63+
if "TEST_OUTPUT_FILES" in integration_test:
64+
_validate_output_path_and_file(config, integration_test["TEST_OUTPUT_FILES"])
65+
66+
if "OUTPUT_FILE" in integration_test:
67+
_validate_output_path_and_file(
68+
config,
69+
[{"PATH_DESCRIPTOR": "OUTPUT_PATH", "FILE": integration_test["OUTPUT_FILE"]}],
70+
)
71+
72+
if "FILE_TYPE" in integration_test:
73+
assert assertions.assert_file_type(
74+
integration_test["FILE_TYPE"],
75+
Path(config["CONFIGURATION"]["OUTPUT_PATH"]).joinpath(
76+
config["CONFIGURATION"]["OUTPUT_FILE"]
77+
),
78+
)
79+
_test_simtel_cfg_files(config, integration_test, from_command_line, from_config_file)
80+
81+
82+
def _test_simtel_cfg_files(config, integration_test, from_command_line, from_config_file):
83+
"""Test simtel cfg files."""
84+
if "TEST_SIMTEL_CFG_FILES" in integration_test:
85+
if from_command_line:
86+
test_simtel_cfg_file = integration_test["TEST_SIMTEL_CFG_FILES"].get(from_command_line)
87+
else:
88+
test_simtel_cfg_file = integration_test["TEST_SIMTEL_CFG_FILES"].get(from_config_file)
89+
if test_simtel_cfg_file:
90+
_validate_simtel_cfg_files(config, test_simtel_cfg_file)
7391

7492

7593
def _validate_reference_output_file(config, integration_test):
@@ -238,3 +256,66 @@ def generate_mask(table, column, condition):
238256
return False
239257

240258
return True
259+
260+
261+
def _validate_simtel_cfg_files(config, simtel_cfg_file):
262+
"""
263+
Check sim_telarray configuration files and compare with reference file.
264+
265+
Note the finetuned naming of configuration files by simtools.
266+
267+
"""
268+
reference_file = Path(simtel_cfg_file)
269+
test_file = Path(config["CONFIGURATION"]["OUTPUT_PATH"]) / reference_file.name.replace(
270+
"_test", f"_{config['CONFIGURATION']['LABEL']}"
271+
)
272+
_logger.info(
273+
f"Comparing simtel cfg files: {reference_file} and {test_file} "
274+
f"for model version {config['CONFIGURATION']['MODEL_VERSION']}"
275+
)
276+
return _compare_simtel_cfg_files(reference_file, test_file)
277+
278+
279+
def _compare_simtel_cfg_files(reference_file, test_file):
280+
"""
281+
Compare two sim_telarray configuration files.
282+
283+
Line-by-line string comparison. Requires similar sequence of
284+
parameters in the files. Ignore lines containing 'config_release'
285+
(as it contains the simtools package version).
286+
287+
Parameters
288+
----------
289+
reference_file: Path
290+
Reference sim_telarray configuration file.
291+
test_file: Path
292+
Test sim_telarray configuration file.
293+
294+
Returns
295+
-------
296+
bool
297+
True if the files are equal.
298+
299+
"""
300+
with open(reference_file, encoding="utf-8") as f1, open(test_file, encoding="utf-8") as f2:
301+
reference_cfg = [line.rstrip() for line in f1 if line.strip()]
302+
test_cfg = [line.rstrip() for line in f2 if line.strip()]
303+
304+
if len(reference_cfg) != len(test_cfg):
305+
_logger.error(
306+
f"Line counts differ: {reference_file} ({len(reference_cfg)} lines), "
307+
f"{test_file} ({len(test_cfg)} lines)."
308+
)
309+
return False
310+
311+
for ref_line, test_line in zip(reference_cfg, test_cfg):
312+
if any(ignore in ref_line for ignore in ("config_release", "Label")):
313+
continue
314+
if ref_line != test_line:
315+
_logger.error(
316+
f"Configuration files {reference_file} and {test_file} do not match: "
317+
f"'{ref_line}' and '{test_line}'"
318+
)
319+
return False
320+
321+
return True

tests/integration_tests/config/simulate_prod_gamma_40_deg_North_check_output.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,15 @@ CTA_SIMPIPE:
3737
# The mean number of photons per telescope after atmospheric absorption and QE
3838
# should be between 90 and 1000 (very loose requirement)
3939
photons: [90, 1000]
40+
- TEST_SIMTEL_CFG_FILES:
41+
5.0.0: tests/resources/sim_telarray_configurations/CTA-North-LSTN-01-5.0.0_test.cfg
42+
6.0.0: tests/resources/sim_telarray_configurations/CTA-North-LSTN-01-6.0.0_test.cfg
43+
- TEST_SIMTEL_CFG_FILES:
44+
5.0.0: tests/resources/sim_telarray_configurations/CTA-North-LSTN-02-5.0.0_test.cfg
45+
6.0.0: tests/resources/sim_telarray_configurations/CTA-North-LSTN-02-6.0.0_test.cfg
46+
- TEST_SIMTEL_CFG_FILES:
47+
5.0.0: tests/resources/sim_telarray_configurations/CTA-North-MSTN-01-5.0.0_test.cfg
48+
6.0.0: tests/resources/sim_telarray_configurations/CTA-North-MSTN-01-6.0.0_test.cfg
49+
- TEST_SIMTEL_CFG_FILES:
50+
5.0.0: tests/resources/sim_telarray_configurations/CTA-alpha-North-5.0.0_test.cfg
51+
6.0.0: tests/resources/sim_telarray_configurations/CTA-alpha-North-6.0.0_test.cfg

tests/integration_tests/config/simulate_prod_gamma_40_deg_South_check_output.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ CTA_SIMPIPE:
66
LABEL: check_output
77
MODEL_VERSION: 6.0.0
88
SITE: South
9-
ARRAY_LAYOUT_NAME: alpha
9+
ARRAY_LAYOUT_NAME: beta
1010
PRIMARY: gamma
1111
RUN_NUMBER_START: 1
1212
NUMBER_OF_RUNS: 1
@@ -24,9 +24,9 @@ CTA_SIMPIPE:
2424
INTEGRATION_TESTS:
2525
- TEST_OUTPUT_FILES:
2626
- PATH_DESCRIPTOR: PACK_FOR_GRID_REGISTER
27-
FILE: run000001_gamma_za40deg_azm180deg_South_alpha_check_output.log_hist.tar.gz
27+
FILE: run000001_gamma_za40deg_azm180deg_South_beta_check_output.log_hist.tar.gz
2828
- PATH_DESCRIPTOR: PACK_FOR_GRID_REGISTER
29-
FILE: run000001_gamma_za40deg_azm180deg_South_alpha_check_output.zst
29+
FILE: run000001_gamma_za40deg_azm180deg_South_beta_check_output.zst
3030
EXPECTED_OUTPUT:
3131
# The mean trigger time for all telescopes should be
3232
# between 0 and 50 ns (very loose requirement)
@@ -37,3 +37,15 @@ CTA_SIMPIPE:
3737
# The mean number of photons per telescope after atmospheric absorption and QE
3838
# should be between 90 and 1000 (very loose requirement)
3939
photons: [90, 1000]
40+
- TEST_SIMTEL_CFG_FILES:
41+
5.0.0: tests/resources/sim_telarray_configurations/CTA-South-LSTS-01-5.0.0_test.cfg
42+
6.0.0: tests/resources/sim_telarray_configurations/CTA-South-LSTS-01-6.0.0_test.cfg
43+
- TEST_SIMTEL_CFG_FILES:
44+
5.0.0: tests/resources/sim_telarray_configurations/CTA-South-MSTS-01-5.0.0_test.cfg
45+
6.0.0: tests/resources/sim_telarray_configurations/CTA-South-MSTS-01-6.0.0_test.cfg
46+
- TEST_SIMTEL_CFG_FILES:
47+
5.0.0: tests/resources/sim_telarray_configurations/CTA-South-SSTS-01-5.0.0_test.cfg
48+
6.0.0: tests/resources/sim_telarray_configurations/CTA-South-SSTS-01-6.0.0_test.cfg
49+
- TEST_SIMTEL_CFG_FILES:
50+
5.0.0: tests/resources/sim_telarray_configurations/CTA-beta-South-5.0.0_test.cfg
51+
6.0.0: tests/resources/sim_telarray_configurations/CTA-beta-South-6.0.0_test.cfg
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
%==================================================
2+
% TELESCOPE CONFIGURATION FILE
3+
% Site: North
4+
% ModelVersion: 5.0.0
5+
% TelescopeModelName: LSTN-01
6+
% Label: check_output
7+
%==================================================
8+
%
9+
#ifdef TELESCOPE
10+
echo Configuration for LSTN-01 - TELESCOPE $(TELESCOPE)
11+
#endif
12+
13+
altitude = 2158.0
14+
asum_clipping = 9999.0
15+
asum_offset = 0.0
16+
asum_shaping_file = none
17+
asum_threshold = 270.0
18+
atmospheric_transmission = atm_trans_2158_1_3_2_0_0_0.1_0.1.dat
19+
axes_offsets = 0.0 0.0
20+
camera_body_diameter = 348.0
21+
camera_body_shape = 2
22+
camera_config_file = camera_CTA-LST-1_analogsum21_v2020-04-14.dat
23+
camera_degraded_efficiency = 1.0
24+
camera_degraded_map = none
25+
camera_depth = 0.0
26+
camera_filter = transmission_lst_window_No7-10_ave.dat
27+
camera_pixels = 1855
28+
camera_transmission = 1.0
29+
channels_per_chip = 4
30+
default_trigger = AnalogSum
31+
disc_ac_coupled = 1
32+
disc_bins = 68
33+
disc_start = 3
34+
discriminator_amplitude = 6.5
35+
discriminator_fall_time = 1.0
36+
discriminator_gate_length = 2.0
37+
discriminator_hysteresis = 0.0
38+
discriminator_output_amplitude = 42.0
39+
discriminator_output_var_percent = 10.0
40+
discriminator_pulse_shape = pulse_LST_8dynode_pix6_20200204.dat
41+
discriminator_rise_time = 1.0
42+
discriminator_scale_threshold = 1.0
43+
discriminator_sigsum_over_threshold = 0.0
44+
discriminator_threshold = 99999.0
45+
discriminator_time_over_threshold = 1.5
46+
discriminator_var_gate_length = 0.1
47+
discriminator_var_sigsum_over_threshold = 0.0
48+
discriminator_var_threshold = 0.2
49+
discriminator_var_time_over_threshold = 0.1
50+
dish_shape_length = 2800.0
51+
effective_focal_length = 2930.57 0.0 0.0 0.0 0.0
52+
fadc_ac_coupled = 1
53+
fadc_amplitude = 25.0
54+
fadc_bins = 75
55+
fadc_compensate_pedestal = -1
56+
fadc_err_compensate_pedestal = 0.0
57+
fadc_err_pedestal = 0.5
58+
fadc_lg_amplitude = 1.28
59+
fadc_lg_compensate_pedestal = -1
60+
fadc_lg_err_compensate_pedestal = -1.0
61+
fadc_lg_err_pedestal = 0.3
62+
fadc_lg_max_signal = 4288
63+
fadc_lg_noise = 5.7
64+
fadc_lg_pedestal = 400.0
65+
fadc_lg_sensitivity = -1.0
66+
fadc_lg_sysvar_pedestal = -1.0
67+
fadc_lg_var_pedestal = 0.4
68+
fadc_lg_var_sensitivity = -1.0
69+
fadc_max_signal = 4249
70+
fadc_max_sum = 16777215
71+
fadc_mhz = 1024.0
72+
fadc_noise = 6.7
73+
fadc_pedestal = 400.0
74+
fadc_pulse_shape = pulse_LST_8dynode_pix6_20200204.dat
75+
fadc_sensitivity = 1.0
76+
fadc_sum_bins = 40
77+
fadc_sum_offset = 9
78+
fadc_sysvar_pedestal = 0.04
79+
fadc_var_pedestal = 0.4
80+
fadc_var_sensitivity = 0.01416
81+
flatfielding = 1
82+
focal_length = 2800.0
83+
focus_offset = 6.55 0.0 0.0 0.0
84+
gain_variation = 0.0187
85+
hg_lg_variation = 0.0
86+
mirror_align_random_distance = 0.0
87+
mirror_align_random_horizontal = 0.0039 28.0 0.0 0.0
88+
mirror_align_random_vertical = 0.0039 28.0 0.0 0.0
89+
mirror_class = 0
90+
mirror_degraded_reflection = 1.0
91+
mirror_focal_length = 0.0
92+
mirror_list = mirror_CTA-N-LST1_v2019-03-31.dat
93+
mirror_offset = 93.25
94+
mirror_reflection_random_angle = 0.0075 0.125 0.037
95+
mirror_reflectivity = ref_LST_2020-04-23.dat
96+
multiplicity_offset = -0.5
97+
nightsky_background = all: 0.238006
98+
nsb_autoscale_airmass = 0.84 0.29
99+
nsb_offaxis = 0.0 0.0 0.0 0.0 0.0
100+
num_gains = 2
101+
only_triggered_telescopes = 1
102+
parabolic_dish = 1
103+
photon_delay = 19.0
104+
pixeltrg_time_step = 0.0
105+
pm_average_gain = 40000.0
106+
pm_collection_efficiency = 1.0
107+
pm_gain_index = 4.5
108+
pm_photoelectron_spectrum = spe_LST_2020-05-09_AP2.0e-4.dat
109+
pm_transit_time = 24.74 9.0 350.0 1066.0
110+
pm_voltage_variation = 0.041
111+
qe_variation = 0.03
112+
quantum_efficiency = qe_lst1_20200318_high+low.dat
113+
random_focal_length = 0.0 0.0
114+
telescope_random_angle = 0.0
115+
telescope_random_error = 0.0
116+
telescope_transmission = 0.969 0.0 0.0 0.0 0.0 0.0
117+
teltrig_min_sigsum = 7.8
118+
teltrig_min_time = 0.5
119+
transit_time_calib_error = 0.0
120+
transit_time_compensate_error = 0.0
121+
transit_time_compensate_step = 0.0
122+
transit_time_error = 0.0
123+
transit_time_jitter = 0.7
124+
trigger_current_limit = 20.0
125+
trigger_delay_compensation = 0.0 0.0 0.0 0.0
126+
trigger_pixels = 3
127+
iobuf_maximum = 1000000000
128+
iobuf_output_maximum = 400000000
129+
min_photoelectrons = 25
130+
min_photons = 300
131+
random_generator = mt19937
132+
sampled_output = 1
133+
save_pe_with_amplitude = 1
134+
store_photoelectrons = 20
135+
tailcut_scale = 2.6
136+
config_release = 5.0.0 written by simtools v0.9.1.dev5+g763c36164
137+
config_version = 5.0.0
138+
camera_config_name = LSTN-01
139+
camera_config_variant =
140+
camera_config_version = 5.0.0
141+
optics_config_name = LSTN-01
142+
optics_config_variant =
143+
optics_config_version = 5.0.0

0 commit comments

Comments
 (0)