gammasimtools 0.9.0__py3-none-any.whl → 0.11.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/METADATA +4 -2
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/RECORD +133 -117
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/entry_points.txt +6 -1
- simtools/_version.py +9 -4
- simtools/applications/calculate_trigger_rate.py +15 -38
- simtools/applications/convert_all_model_parameters_from_simtel.py +9 -29
- simtools/applications/convert_geo_coordinates_of_array_elements.py +47 -45
- simtools/applications/convert_model_parameter_from_simtel.py +2 -3
- simtools/applications/db_add_file_to_db.py +1 -3
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +110 -0
- simtools/applications/db_add_value_from_json_to_db.py +1 -2
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +6 -6
- simtools/applications/db_get_file_from_db.py +11 -12
- simtools/applications/db_get_parameter_from_db.py +26 -35
- simtools/applications/derive_mirror_rnda.py +1 -2
- simtools/applications/derive_photon_electron_spectrum.py +99 -0
- simtools/applications/derive_psf_parameters.py +1 -0
- simtools/applications/docs_produce_array_element_report.py +71 -0
- simtools/applications/docs_produce_model_parameter_reports.py +63 -0
- simtools/applications/generate_array_config.py +17 -17
- simtools/applications/generate_corsika_histograms.py +2 -2
- simtools/applications/generate_regular_arrays.py +19 -17
- simtools/applications/generate_simtel_array_histograms.py +11 -48
- simtools/applications/production_derive_limits.py +95 -0
- simtools/applications/production_generate_simulation_config.py +37 -33
- simtools/applications/production_scale_events.py +4 -9
- simtools/applications/run_application.py +165 -0
- simtools/applications/simulate_light_emission.py +0 -4
- simtools/applications/simulate_prod.py +1 -1
- simtools/applications/simulate_prod_htcondor_generator.py +26 -26
- simtools/applications/submit_data_from_external.py +12 -4
- simtools/applications/submit_model_parameter_from_external.py +18 -11
- simtools/applications/validate_camera_efficiency.py +2 -2
- simtools/applications/validate_file_using_schema.py +26 -22
- simtools/camera/single_photon_electron_spectrum.py +168 -0
- simtools/configuration/commandline_parser.py +37 -1
- simtools/configuration/configurator.py +8 -10
- simtools/constants.py +10 -3
- simtools/corsika/corsika_config.py +19 -17
- simtools/corsika/corsika_histograms.py +5 -7
- simtools/corsika/corsika_histograms_visualize.py +2 -4
- simtools/data_model/data_reader.py +0 -3
- simtools/data_model/metadata_collector.py +20 -12
- simtools/data_model/metadata_model.py +8 -124
- simtools/data_model/model_data_writer.py +81 -75
- simtools/data_model/schema.py +220 -0
- simtools/data_model/validate_data.py +79 -68
- simtools/db/db_handler.py +350 -492
- simtools/db/db_model_upload.py +139 -0
- simtools/dependencies.py +112 -0
- simtools/io_operations/hdf5_handler.py +54 -24
- simtools/layout/array_layout.py +38 -32
- simtools/model/array_model.py +13 -7
- simtools/model/model_parameter.py +55 -54
- simtools/model/site_model.py +2 -2
- simtools/production_configuration/calculate_statistical_errors_grid_point.py +119 -145
- simtools/production_configuration/event_scaler.py +9 -35
- simtools/production_configuration/generate_simulation_config.py +9 -44
- simtools/production_configuration/interpolation_handler.py +9 -15
- simtools/production_configuration/limits_calculation.py +202 -0
- simtools/reporting/docs_read_parameters.py +310 -0
- simtools/runners/corsika_simtel_runner.py +4 -4
- simtools/schemas/{integration_tests_config.metaschema.yml → application_workflow.metaschema.yml} +61 -27
- simtools/schemas/array_elements.yml +8 -0
- simtools/schemas/input/MST_mirror_2f_measurements.schema.yml +39 -0
- simtools/schemas/input/single_pe_spectrum.schema.yml +38 -0
- simtools/schemas/model_parameter.metaschema.yml +103 -2
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +4 -1
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +1 -1
- simtools/schemas/model_parameters/array_window.schema.yml +37 -0
- simtools/schemas/model_parameters/asum_clipping.schema.yml +0 -4
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
- simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_cherenkov_photon_bunch_size.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_cherenkov_photon_wavelength_range.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_first_interaction_height.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +4 -2
- simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_longitudinal_shower_development.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_particle_kinetic_energy_cutoff.schema.yml +2 -0
- simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +2 -0
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_offset.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_pedsub.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +0 -2
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +0 -2
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_noise.schema.yml +3 -3
- simtools/schemas/model_parameters/fake_mirror_list.schema.yml +33 -0
- simtools/schemas/model_parameters/iobuf_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_photons.schema.yml +2 -2
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +1 -1
- simtools/schemas/model_parameters/min_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/min_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/random_generator.schema.yml +1 -1
- simtools/schemas/model_parameters/sampled_output.schema.yml +1 -1
- simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/store_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/tailcut_scale.schema.yml +1 -1
- simtools/schemas/production_configuration_metrics.schema.yml +68 -0
- simtools/schemas/production_tables.schema.yml +41 -0
- simtools/simtel/simtel_config_reader.py +1 -2
- simtools/simtel/simtel_config_writer.py +6 -8
- simtools/simtel/simtel_io_histogram.py +32 -68
- simtools/simtel/simtel_io_histograms.py +17 -34
- simtools/simtel/simulator_array.py +2 -1
- simtools/simtel/simulator_camera_efficiency.py +6 -3
- simtools/simtel/simulator_light_emission.py +5 -6
- simtools/simtel/simulator_ray_tracing.py +3 -4
- simtools/testing/configuration.py +2 -1
- simtools/testing/helpers.py +6 -13
- simtools/testing/validate_output.py +141 -47
- simtools/utils/general.py +114 -14
- simtools/utils/names.py +299 -157
- simtools/utils/value_conversion.py +17 -13
- simtools/version.py +2 -2
- simtools/visualization/legend_handlers.py +2 -0
- simtools/applications/db_add_model_parameters_from_repository_to_db.py +0 -176
- simtools/db/db_array_elements.py +0 -130
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/LICENSE +0 -0
- {gammasimtools-0.9.0.dist-info → gammasimtools-0.11.0.dist-info}/top_level.txt +0 -0
- /simtools/{camera_efficiency.py → camera/camera_efficiency.py} +0 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
|
|
3
|
+
r"""
|
|
4
|
+
Derives the limits for energy, radial distance, and viewcone to be used in CORSIKA simulations.
|
|
5
|
+
|
|
6
|
+
The limits are derived based on the event loss fraction specified by the user.
|
|
7
|
+
|
|
8
|
+
Command line arguments
|
|
9
|
+
----------------------
|
|
10
|
+
event_data_file (str, required)
|
|
11
|
+
Path to the file containing the event data.
|
|
12
|
+
loss_fraction (float, required)
|
|
13
|
+
Fraction of events to be lost.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Example
|
|
17
|
+
-------
|
|
18
|
+
Derive limits for a given file with a specified loss fraction.
|
|
19
|
+
|
|
20
|
+
.. code-block:: console
|
|
21
|
+
|
|
22
|
+
simtools-production-derive-limits\\
|
|
23
|
+
--event_data_file path/to/event_data_file.hdf5 \\
|
|
24
|
+
--loss_fraction 1e-6
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
import logging
|
|
28
|
+
|
|
29
|
+
import simtools.utils.general as gen
|
|
30
|
+
from simtools.configuration import configurator
|
|
31
|
+
from simtools.io_operations.hdf5_handler import read_hdf5
|
|
32
|
+
from simtools.production_configuration.limits_calculation import LimitCalculator
|
|
33
|
+
|
|
34
|
+
_logger = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _parse():
|
|
38
|
+
"""
|
|
39
|
+
Parse command line configuration.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
event_data_file: str
|
|
44
|
+
The event data file.
|
|
45
|
+
loss_fraction: float
|
|
46
|
+
Loss fraction of events for limit derivation.
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
CommandLineParser
|
|
51
|
+
Command line parser object
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
config = configurator.Configurator(
|
|
55
|
+
description="Derive limits for energy, radial distance, and viewcone."
|
|
56
|
+
)
|
|
57
|
+
config.parser.add_argument(
|
|
58
|
+
"--event_data_file",
|
|
59
|
+
type=str,
|
|
60
|
+
required=True,
|
|
61
|
+
help="Path to the event data file containing the event data.",
|
|
62
|
+
)
|
|
63
|
+
config.parser.add_argument(
|
|
64
|
+
"--loss_fraction", type=float, required=True, help="Fraction of events to be lost."
|
|
65
|
+
)
|
|
66
|
+
return config.initialize(db_config=False)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def main():
|
|
70
|
+
"""Derive limits for energy, radial distance, and viewcone."""
|
|
71
|
+
args_dict, _ = _parse()
|
|
72
|
+
|
|
73
|
+
logger = logging.getLogger()
|
|
74
|
+
logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
|
|
75
|
+
|
|
76
|
+
event_data_file_path = args_dict["event_data_file"]
|
|
77
|
+
loss_fraction = args_dict["loss_fraction"]
|
|
78
|
+
|
|
79
|
+
_logger.info(f"Loading event data file: {event_data_file_path}")
|
|
80
|
+
tables = read_hdf5(event_data_file_path)
|
|
81
|
+
|
|
82
|
+
calculator = LimitCalculator(tables)
|
|
83
|
+
|
|
84
|
+
lower_energy_limit = calculator.compute_lower_energy_limit(loss_fraction)
|
|
85
|
+
_logger.info(f"Lower energy threshold: {lower_energy_limit}")
|
|
86
|
+
|
|
87
|
+
upper_radial_distance = calculator.compute_upper_radial_distance(loss_fraction)
|
|
88
|
+
_logger.info(f"Upper radius threshold: {upper_radial_distance}")
|
|
89
|
+
|
|
90
|
+
viewcone = calculator.compute_viewcone(loss_fraction)
|
|
91
|
+
_logger.info(f"Viewcone radius: {viewcone}")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if __name__ == "__main__":
|
|
95
|
+
main()
|
|
@@ -1,32 +1,42 @@
|
|
|
1
1
|
#!/usr/bin/python3
|
|
2
2
|
|
|
3
3
|
r"""
|
|
4
|
-
|
|
4
|
+
Derive simulation configuration parameters for a simulation production.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Derived simulation configuration parameters include:
|
|
7
|
+
|
|
8
|
+
* energy range
|
|
9
|
+
* shower core scatter radius
|
|
10
|
+
* view cone radius
|
|
11
|
+
* total number of events to be simulated
|
|
12
|
+
|
|
13
|
+
Configuration parameters depend on characteristics of the observations, especially elevation,
|
|
14
|
+
azimuth, and night sky background.
|
|
15
|
+
|
|
16
|
+
The configuration parameters are derived according to the required precision. The metrics are:
|
|
17
|
+
|
|
18
|
+
* statistical uncertainty on the determination of the effective area as function of primary energy
|
|
19
|
+
* fraction of lost events to the selected core scatter and view cone radius (to be implemented)
|
|
20
|
+
* statistical uncertainty of the energy migration matrix as function of primary energy
|
|
21
|
+
(to be implemented)
|
|
9
22
|
|
|
10
23
|
Command line arguments
|
|
11
24
|
----------------------
|
|
12
25
|
azimuth (float, required)
|
|
13
|
-
|
|
26
|
+
Azimuth angle in degrees.
|
|
14
27
|
elevation (float, required)
|
|
15
|
-
|
|
28
|
+
Elevation angle in degrees.
|
|
16
29
|
nsb (float, required)
|
|
17
|
-
|
|
18
|
-
ctao_data_level (str, required)
|
|
19
|
-
The data level for the simulation (e.g., 'A', 'B', 'C').
|
|
20
|
-
science_case (str, required)
|
|
21
|
-
The science case for the simulation.
|
|
30
|
+
Night sky background value.
|
|
22
31
|
file_path (str, required)
|
|
23
|
-
|
|
32
|
+
Path to file with MC events at CTAO DL2 data level.
|
|
33
|
+
Used for statistical uncertainty evaluation.
|
|
24
34
|
file_type (str, required)
|
|
25
|
-
|
|
26
|
-
metrics (str,
|
|
27
|
-
|
|
35
|
+
Type of the DL2 MC event file ('point-like' or 'cone').
|
|
36
|
+
metrics (str, required)
|
|
37
|
+
Path to a YAML file containing metrics for evaluation.
|
|
28
38
|
site (str, required)
|
|
29
|
-
|
|
39
|
+
The observatory site (North or South).
|
|
30
40
|
|
|
31
41
|
Example
|
|
32
42
|
-------
|
|
@@ -34,13 +44,12 @@ To run the simulation configuration, execute the script as follows:
|
|
|
34
44
|
|
|
35
45
|
.. code-block:: console
|
|
36
46
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
--metrics_file tests/resources/production_simulation_config_metrics.yaml --site North
|
|
47
|
+
simtools-production-generate-simulation-config --azimuth 60.0 --elevation 45.0 \
|
|
48
|
+
--nsb 0.3 --file_path tests/resources/production_dl2_fits/dl2_mc_events_file.fits \
|
|
49
|
+
--file_type "point-like" \
|
|
50
|
+
--metrics_file tests/resources/production_simulation_config_metrics.yml --site North
|
|
42
51
|
|
|
43
|
-
The output will show the
|
|
52
|
+
The output will show the derived simulation parameters.
|
|
44
53
|
"""
|
|
45
54
|
|
|
46
55
|
import json
|
|
@@ -51,6 +60,7 @@ import astropy.units as u
|
|
|
51
60
|
|
|
52
61
|
import simtools.utils.general as gen
|
|
53
62
|
from simtools.configuration import configurator
|
|
63
|
+
from simtools.data_model import schema
|
|
54
64
|
from simtools.io_operations import io_handler
|
|
55
65
|
from simtools.production_configuration.generate_simulation_config import (
|
|
56
66
|
SimulationConfig,
|
|
@@ -60,7 +70,8 @@ from simtools.production_configuration.generate_simulation_config import (
|
|
|
60
70
|
def _parse(label):
|
|
61
71
|
"""Parse command-line arguments."""
|
|
62
72
|
config = configurator.Configurator(
|
|
63
|
-
label=label,
|
|
73
|
+
label=label,
|
|
74
|
+
description="Derive simulation configuration parameters for a simulation production.",
|
|
64
75
|
)
|
|
65
76
|
config.parser.add_argument(
|
|
66
77
|
"--azimuth", type=float, required=True, help="Azimuth angle in degrees."
|
|
@@ -71,12 +82,6 @@ def _parse(label):
|
|
|
71
82
|
config.parser.add_argument(
|
|
72
83
|
"--nsb", type=float, required=True, help="Night sky background in units of 1/(sr*ns*cm**2)."
|
|
73
84
|
)
|
|
74
|
-
config.parser.add_argument(
|
|
75
|
-
"--ctao_data_level", type=str, required=True, help="Data level (e.g., 'A', 'B', 'C')."
|
|
76
|
-
)
|
|
77
|
-
config.parser.add_argument(
|
|
78
|
-
"--science_case", type=str, required=True, help="Science case for the simulation."
|
|
79
|
-
)
|
|
80
85
|
config.parser.add_argument(
|
|
81
86
|
"--file_path", type=str, required=True, help="Path to MC event file in DL2 format."
|
|
82
87
|
)
|
|
@@ -125,14 +130,13 @@ def main():
|
|
|
125
130
|
"night_sky_background": args_dict["nsb"],
|
|
126
131
|
}
|
|
127
132
|
|
|
128
|
-
metrics = (
|
|
129
|
-
|
|
133
|
+
metrics = gen.collect_data_from_file(args_dict["metrics_file"])
|
|
134
|
+
schema.validate_dict_using_schema(
|
|
135
|
+
data=metrics, schema_file="production_configuration_metrics.schema.yml"
|
|
130
136
|
)
|
|
131
137
|
|
|
132
138
|
simulation_config = SimulationConfig(
|
|
133
139
|
grid_point=grid_point_config,
|
|
134
|
-
ctao_data_level=args_dict["ctao_data_level"],
|
|
135
|
-
science_case=args_dict["science_case"],
|
|
136
140
|
file_path=args_dict["file_path"],
|
|
137
141
|
file_type=args_dict["file_type"],
|
|
138
142
|
metrics=metrics,
|
|
@@ -28,7 +28,7 @@ To evaluate statistical uncertainties and perform interpolation, run the command
|
|
|
28
28
|
|
|
29
29
|
simtools-production-scale-events --base_path tests/resources/production_dl2_fits/ \
|
|
30
30
|
--zeniths 20 52 40 60 --offsets 0 --interpolate --query_point 1 180 30 0 0 \
|
|
31
|
-
--
|
|
31
|
+
--metrics_file "path/to/metrics.yaml"
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
The output will display the scaled events for the specified grid point.
|
|
@@ -93,11 +93,8 @@ def _parse(label, description):
|
|
|
93
93
|
config.parser.add_argument(
|
|
94
94
|
"--metrics_file",
|
|
95
95
|
type=str,
|
|
96
|
-
default="production_simulation_config_metrics.
|
|
97
|
-
help="Metrics definition file. (default: production_simulation_config_metrics.
|
|
98
|
-
)
|
|
99
|
-
config.parser.add_argument(
|
|
100
|
-
"--science_case", type=str, required=True, help="Science case for the simulation."
|
|
96
|
+
default="production_simulation_config_metrics.yml",
|
|
97
|
+
help="Metrics definition file. (default: production_simulation_config_metrics.yml)",
|
|
101
98
|
)
|
|
102
99
|
return config.initialize(db_config=False)
|
|
103
100
|
|
|
@@ -147,9 +144,7 @@ def main():
|
|
|
147
144
|
logger.warning(f"Offsets: {args_dict['offsets']}")
|
|
148
145
|
|
|
149
146
|
# Perform interpolation for the given query point
|
|
150
|
-
interpolation_handler = InterpolationHandler(
|
|
151
|
-
evaluator_instances, science_case=args_dict["science_case"], metrics=metrics
|
|
152
|
-
)
|
|
147
|
+
interpolation_handler = InterpolationHandler(evaluator_instances, metrics=metrics)
|
|
153
148
|
query_points = np.array([args_dict["query_point"]])
|
|
154
149
|
scaled_events = interpolation_handler.interpolate(query_points)
|
|
155
150
|
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Run simtools applications from configuration files for setting workflows.
|
|
5
|
+
|
|
6
|
+
Allows to run several simtools applications with a single configuration file, which includes
|
|
7
|
+
both the name of the simtools application and the configuration for the application.
|
|
8
|
+
|
|
9
|
+
Strong assumption on the directory structure for input and output files of applications.
|
|
10
|
+
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import logging
|
|
14
|
+
import subprocess
|
|
15
|
+
import tempfile
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
import yaml
|
|
19
|
+
|
|
20
|
+
import simtools.utils.general as gen
|
|
21
|
+
from simtools import dependencies
|
|
22
|
+
from simtools.configuration import configurator
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _parse(label, description, usage):
|
|
26
|
+
"""
|
|
27
|
+
Parse command line configuration.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
label : str
|
|
32
|
+
Label describing the application.
|
|
33
|
+
description : str
|
|
34
|
+
Description of the application.
|
|
35
|
+
usage : str
|
|
36
|
+
Example on how to use the application.
|
|
37
|
+
|
|
38
|
+
Returns
|
|
39
|
+
-------
|
|
40
|
+
CommandLineParser
|
|
41
|
+
Command line parser object.
|
|
42
|
+
"""
|
|
43
|
+
config = configurator.Configurator(label=label, description=description, usage=usage)
|
|
44
|
+
|
|
45
|
+
config.parser.add_argument(
|
|
46
|
+
"--configuration_file",
|
|
47
|
+
help="Application configuration.",
|
|
48
|
+
type=str,
|
|
49
|
+
required=True,
|
|
50
|
+
default=None,
|
|
51
|
+
)
|
|
52
|
+
return config.initialize(db_config=False)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def run_application(application, configuration, logger):
|
|
56
|
+
"""Run a simtools application and return stdout and stderr."""
|
|
57
|
+
with tempfile.NamedTemporaryFile(mode="w", delete=True, suffix=".yml") as temp_config:
|
|
58
|
+
yaml.dump(configuration, temp_config, default_flow_style=False)
|
|
59
|
+
temp_config.flush()
|
|
60
|
+
configuration_file = Path(temp_config.name)
|
|
61
|
+
try:
|
|
62
|
+
result = subprocess.run(
|
|
63
|
+
[application, "--config", configuration_file],
|
|
64
|
+
check=True,
|
|
65
|
+
capture_output=True,
|
|
66
|
+
text=True,
|
|
67
|
+
)
|
|
68
|
+
except subprocess.CalledProcessError as exc:
|
|
69
|
+
logger.error(f"Error running application {application}: {exc.stderr}")
|
|
70
|
+
raise exc
|
|
71
|
+
return result.stdout, result.stderr
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_subdirectory_name(path):
|
|
75
|
+
"""Get the first subdirectory name under 'input'."""
|
|
76
|
+
path = Path(path).resolve()
|
|
77
|
+
try:
|
|
78
|
+
input_index = path.parts.index("input")
|
|
79
|
+
return path.parts[input_index], path.parts[input_index + 1]
|
|
80
|
+
except (ValueError, IndexError) as exc:
|
|
81
|
+
raise ValueError(f"Could not find subdirectory under 'input': {exc}") from exc
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def read_application_configuration(configuration_file, logger):
|
|
85
|
+
"""
|
|
86
|
+
Read application configuration from file and modify for setting workflows.
|
|
87
|
+
|
|
88
|
+
Strong assumptions on the structure of input and output files:
|
|
89
|
+
|
|
90
|
+
- configuration file is expected to be in './input/<workflow directory>/<yaml file>'
|
|
91
|
+
- output files will be written out to './output/<workflow directory>/'
|
|
92
|
+
|
|
93
|
+
Replaces the placeholders in the configuration file with the actual values.
|
|
94
|
+
Sets 'USE_PLAIN_OUTPUT_PATH' to True for all applications.
|
|
95
|
+
|
|
96
|
+
Parameters
|
|
97
|
+
----------
|
|
98
|
+
configuration_file : str
|
|
99
|
+
Configuration file name.
|
|
100
|
+
logger : Logger
|
|
101
|
+
Logger object.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
dict
|
|
106
|
+
Application configuration.
|
|
107
|
+
Path
|
|
108
|
+
Path to the log file.
|
|
109
|
+
|
|
110
|
+
"""
|
|
111
|
+
application_config = gen.collect_data_from_file(configuration_file).get("CTA_SIMPIPE")
|
|
112
|
+
place_holder = "__SETTING_WORKFLOW__"
|
|
113
|
+
workflow_dir, setting_workflow = get_subdirectory_name(configuration_file)
|
|
114
|
+
output_path = str(workflow_dir).replace("input", "output") + setting_workflow
|
|
115
|
+
logger.info(f"Setting workflow output path to {output_path}")
|
|
116
|
+
log_file = (
|
|
117
|
+
Path(application_config.get("LOG_PATH", "./").replace(place_holder, setting_workflow))
|
|
118
|
+
/ "simtools.log"
|
|
119
|
+
)
|
|
120
|
+
log_file.parent.mkdir(parents=True, exist_ok=True)
|
|
121
|
+
configurations = application_config.get("APPLICATIONS")
|
|
122
|
+
for config in configurations:
|
|
123
|
+
for key, value in config.get("CONFIGURATION", {}).items():
|
|
124
|
+
if isinstance(value, str):
|
|
125
|
+
config["CONFIGURATION"][key] = value.replace(place_holder, setting_workflow)
|
|
126
|
+
if isinstance(value, list):
|
|
127
|
+
config["CONFIGURATION"][key] = [
|
|
128
|
+
item.replace(place_holder, setting_workflow) for item in value
|
|
129
|
+
]
|
|
130
|
+
config["CONFIGURATION"]["USE_PLAIN_OUTPUT_PATH"] = True
|
|
131
|
+
config["OUTPUT_PATH"] = output_path
|
|
132
|
+
|
|
133
|
+
return configurations, log_file
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def main(): # noqa: D103
|
|
137
|
+
args_dict, _ = _parse(
|
|
138
|
+
Path(__file__).stem,
|
|
139
|
+
description="Run simtools applications from configuration file.",
|
|
140
|
+
usage="simtools-run-application --config_file config_file_name",
|
|
141
|
+
)
|
|
142
|
+
logger = logging.getLogger()
|
|
143
|
+
logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
|
|
144
|
+
|
|
145
|
+
configurations, log_file = read_application_configuration(
|
|
146
|
+
args_dict["configuration_file"], logger
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
with log_file.open("w", encoding="utf-8") as file:
|
|
150
|
+
file.write("Running simtools applications\n")
|
|
151
|
+
file.write(dependencies.get_version_string())
|
|
152
|
+
for config in configurations:
|
|
153
|
+
logger.info(f"Running application: {config.get('APPLICATION')}")
|
|
154
|
+
config = gen.change_dict_keys_case(config, False)
|
|
155
|
+
stdout, stderr = run_application(
|
|
156
|
+
config.get("APPLICATION"), config.get("CONFIGURATION"), logger
|
|
157
|
+
)
|
|
158
|
+
file.write("=" * 80 + "\n")
|
|
159
|
+
file.write(f"Application: {config.get('APPLICATION')}\n")
|
|
160
|
+
file.write("STDOUT:\n" + stdout)
|
|
161
|
+
file.write("STDERR:\n" + stderr)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
if __name__ == "__main__":
|
|
165
|
+
main()
|
|
@@ -117,7 +117,6 @@ r"""
|
|
|
117
117
|
|
|
118
118
|
"""
|
|
119
119
|
|
|
120
|
-
|
|
121
120
|
import logging
|
|
122
121
|
import subprocess
|
|
123
122
|
from pathlib import Path
|
|
@@ -390,7 +389,6 @@ def main():
|
|
|
390
389
|
run_script = light_source.prepare_script(generate_postscript=True, **args_dict)
|
|
391
390
|
log_file = f"{light_source.output_directory}/logfile.log"
|
|
392
391
|
with open(log_file, "w", encoding="utf-8") as log_file:
|
|
393
|
-
|
|
394
392
|
subprocess.run(
|
|
395
393
|
run_script,
|
|
396
394
|
shell=False,
|
|
@@ -430,7 +428,6 @@ def main():
|
|
|
430
428
|
)
|
|
431
429
|
|
|
432
430
|
elif args_dict["light_source_setup"] == "layout":
|
|
433
|
-
|
|
434
431
|
light_source = SimulatorLightEmission(
|
|
435
432
|
telescope_model=telescope_model,
|
|
436
433
|
calibration_model=calibration_model,
|
|
@@ -443,7 +440,6 @@ def main():
|
|
|
443
440
|
run_script = light_source.prepare_script(generate_postscript=True, **args_dict)
|
|
444
441
|
log_file = f"{light_source.output_directory}/logfile.log"
|
|
445
442
|
with open(log_file, "w", encoding="utf-8") as log_file:
|
|
446
|
-
|
|
447
443
|
subprocess.run(
|
|
448
444
|
run_script, shell=False, check=False, text=True, stdout=log_file, stderr=log_file
|
|
449
445
|
)
|
|
@@ -31,7 +31,7 @@ r"""
|
|
|
31
31
|
Zenith angle in degrees.
|
|
32
32
|
nshow (int, optional)
|
|
33
33
|
Number of showers to simulate.
|
|
34
|
-
The Number of simulated events depends on the number of times a shower is
|
|
34
|
+
The Number of simulated events depends on the number of times a shower is reused in the
|
|
35
35
|
telescope simulation. The number provided here is before any reuse factors.
|
|
36
36
|
start_run (int, required)
|
|
37
37
|
Start run number such that the actual run number will be 'start_run' + 'run'.
|
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/python3
|
|
2
2
|
|
|
3
3
|
r"""
|
|
4
|
-
|
|
4
|
+
Generate a run script and submit file for HT Condor job submission of a simulation production.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
This tool facilitates the submission of multiple simulations to the HT Condor batch system,
|
|
7
|
+
enabling:
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
- Execution of simulations using the "simtools-simulate-prod" application.
|
|
10
|
+
- 'number_of_runs' jobs are submitted to the HT Condor batch system.
|
|
11
|
+
- Utilization of an Apptainer image containing the SimPipe simulation software and tools.
|
|
12
|
+
- Packaging of data and histogram files, and writing them to a specified directory.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
This tool is intended for use in an HT Condor environment. Jobs run in a container universe
|
|
15
|
+
using the Apptainer image specified in the command line ('--apptainer_image'). Output is written
|
|
16
|
+
to the 'output_path' directory, with 'simtools-output' and 'logs' subdirectories.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Requirements for the 'simtools-simulate-prod-htcondor-generator' application:
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
- Availability of an Apptainer image 'simtools-prod' (obtainable from the package registry on
|
|
21
|
+
GitHub, e.g., via 'apptainer pull --force docker://ghcr.io/gammasim/simtools-prod:latest').
|
|
22
|
+
- Environment parameters required to run CORSIKA and sim_telarray, as well as DB access
|
|
23
|
+
credentials. These should be listed similarly to a '.env' file and copied to
|
|
24
|
+
'output_path/env.txt'. Ensure that the path to the simulation software is correctly set to
|
|
25
|
+
'SIMTOOLS_SIMTEL_PATH=/workdir/sim_telarray'.
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
Command line arguments
|
|
29
|
+
----------------------
|
|
30
|
+
output_path (str, required)
|
|
31
|
+
Directory where the output and the simulation data files will be written.
|
|
32
|
+
apptainer_image (str, optional)
|
|
33
|
+
Apptainer image to use for the simulation (full path).
|
|
34
|
+
priority (int, optional)
|
|
35
|
+
Job priority (default: 1).
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
(all other command line arguments are identical to those of :ref:`simulate_prod`).
|
|
38
38
|
|
|
39
39
|
"""
|
|
40
40
|
|
|
@@ -24,7 +24,7 @@ r"""
|
|
|
24
24
|
simtools-submit-data-from-external \\
|
|
25
25
|
--input_meta ./tests/resources/MLTdata-preproduction.meta.yml \\
|
|
26
26
|
--input ./tests/resources/MLTdata-preproduction.ecsv \\
|
|
27
|
-
--schema
|
|
27
|
+
--schema src/simtools/schemas/input/MST_mirror_2f_measurements.schema.yml \\
|
|
28
28
|
--output_file TEST-submit_data_from_external.ecsv
|
|
29
29
|
|
|
30
30
|
Expected final print-out message:
|
|
@@ -83,6 +83,12 @@ def _parse(label, description):
|
|
|
83
83
|
type=str,
|
|
84
84
|
required=False,
|
|
85
85
|
)
|
|
86
|
+
config.parser.add_argument(
|
|
87
|
+
"--ignore_metadata",
|
|
88
|
+
help="Ignore metadata",
|
|
89
|
+
action="store_true",
|
|
90
|
+
required=False,
|
|
91
|
+
)
|
|
86
92
|
return config.initialize(output=True)
|
|
87
93
|
|
|
88
94
|
|
|
@@ -95,16 +101,18 @@ def main(): # noqa: D103
|
|
|
95
101
|
logger = logging.getLogger()
|
|
96
102
|
logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
|
|
97
103
|
|
|
98
|
-
_metadata = MetadataCollector(args_dict
|
|
104
|
+
_metadata = None if args_dict.get("ignore_metadata") else MetadataCollector(args_dict)
|
|
99
105
|
|
|
100
106
|
data_validator = validate_data.DataValidator(
|
|
101
|
-
schema_file=
|
|
107
|
+
schema_file=(
|
|
108
|
+
_metadata.get_data_model_schema_file_name() if _metadata else args_dict.get("schema")
|
|
109
|
+
),
|
|
102
110
|
data_file=args_dict["input"],
|
|
103
111
|
)
|
|
104
112
|
|
|
105
113
|
writer.ModelDataWriter.dump(
|
|
106
114
|
args_dict=args_dict,
|
|
107
|
-
metadata=_metadata.get_top_level_metadata(),
|
|
115
|
+
metadata=_metadata.get_top_level_metadata() if _metadata else None,
|
|
108
116
|
product_data=data_validator.validate_and_transform(),
|
|
109
117
|
)
|
|
110
118
|
|
|
@@ -16,8 +16,8 @@ r"""
|
|
|
16
16
|
instrument name.
|
|
17
17
|
site (str)
|
|
18
18
|
site location.
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
parameter_version (str)
|
|
20
|
+
Parameter version.
|
|
21
21
|
input_meta (str, optional)
|
|
22
22
|
input meta data file (yml format)
|
|
23
23
|
|
|
@@ -33,7 +33,7 @@ r"""
|
|
|
33
33
|
--value 2 \\
|
|
34
34
|
--instrument LSTN-design \\
|
|
35
35
|
--site North \\
|
|
36
|
-
--
|
|
36
|
+
--parameter_version 0.1.0 \\
|
|
37
37
|
--input_meta num_gains.metadata.yml
|
|
38
38
|
|
|
39
39
|
"""
|
|
@@ -70,8 +70,9 @@ def _parse(label, description):
|
|
|
70
70
|
)
|
|
71
71
|
config.parser.add_argument("--instrument", type=str, required=True, help="Instrument name")
|
|
72
72
|
config.parser.add_argument("--site", type=str, required=True, help="Site location")
|
|
73
|
-
config.parser.add_argument(
|
|
74
|
-
|
|
73
|
+
config.parser.add_argument(
|
|
74
|
+
"--parameter_version", type=str, required=True, help="Parameter version"
|
|
75
|
+
)
|
|
75
76
|
config.parser.add_argument(
|
|
76
77
|
"--value",
|
|
77
78
|
type=str,
|
|
@@ -82,18 +83,22 @@ def _parse(label, description):
|
|
|
82
83
|
'Examples: "--value=5", "--value=\'5 km\'", "--value=\'5 cm, 0.5 deg\'"'
|
|
83
84
|
),
|
|
84
85
|
)
|
|
85
|
-
|
|
86
86
|
config.parser.add_argument(
|
|
87
87
|
"--input_meta",
|
|
88
88
|
help="meta data file associated to input data",
|
|
89
89
|
type=str,
|
|
90
90
|
required=False,
|
|
91
91
|
)
|
|
92
|
-
|
|
92
|
+
config.parser.add_argument(
|
|
93
|
+
"--check_parameter_version",
|
|
94
|
+
help="Check if the parameter version exists in the database",
|
|
95
|
+
action="store_true",
|
|
96
|
+
)
|
|
97
|
+
return config.initialize(output=True, db_config=True)
|
|
93
98
|
|
|
94
99
|
|
|
95
100
|
def main(): # noqa: D103
|
|
96
|
-
args_dict,
|
|
101
|
+
args_dict, db_config = _parse(
|
|
97
102
|
label=Path(__file__).stem,
|
|
98
103
|
description="Submit and validate a model parameters).",
|
|
99
104
|
)
|
|
@@ -102,19 +107,21 @@ def main(): # noqa: D103
|
|
|
102
107
|
logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"]))
|
|
103
108
|
|
|
104
109
|
output_path = (
|
|
105
|
-
Path(args_dict["output_path"]) / args_dict["
|
|
110
|
+
Path(args_dict["output_path"]) / args_dict["instrument"] / args_dict["parameter"]
|
|
106
111
|
if args_dict.get("output_path")
|
|
107
112
|
else None
|
|
108
113
|
)
|
|
114
|
+
|
|
109
115
|
writer.ModelDataWriter.dump_model_parameter(
|
|
110
116
|
parameter_name=args_dict["parameter"],
|
|
111
117
|
value=args_dict["value"],
|
|
112
118
|
instrument=args_dict["instrument"],
|
|
113
|
-
|
|
114
|
-
output_file=Path(args_dict["parameter"]
|
|
119
|
+
parameter_version=args_dict["parameter_version"],
|
|
120
|
+
output_file=Path(args_dict["parameter"] + "-" + args_dict["parameter_version"] + ".json"),
|
|
115
121
|
output_path=output_path,
|
|
116
122
|
use_plain_output_path=args_dict.get("use_plain_output_path"),
|
|
117
123
|
metadata_input_dict=args_dict,
|
|
124
|
+
db_config=db_config if args_dict.get("check_parameter_version") else None,
|
|
118
125
|
)
|
|
119
126
|
|
|
120
127
|
|
|
@@ -47,7 +47,7 @@ import logging
|
|
|
47
47
|
from pathlib import Path
|
|
48
48
|
|
|
49
49
|
import simtools.utils.general as gen
|
|
50
|
-
from simtools.camera_efficiency import CameraEfficiency
|
|
50
|
+
from simtools.camera.camera_efficiency import CameraEfficiency
|
|
51
51
|
from simtools.configuration import configurator
|
|
52
52
|
|
|
53
53
|
|
|
@@ -106,7 +106,7 @@ def main(): # noqa: D103
|
|
|
106
106
|
ce = CameraEfficiency(
|
|
107
107
|
db_config=_db_config,
|
|
108
108
|
simtel_path=args_dict["simtel_path"],
|
|
109
|
-
label=label,
|
|
109
|
+
label=args_dict.get("label", label),
|
|
110
110
|
config_data=args_dict,
|
|
111
111
|
)
|
|
112
112
|
ce.simulate()
|