gammasimtools 0.24.0__py3-none-any.whl → 0.25.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.
Files changed (59) hide show
  1. {gammasimtools-0.24.0.dist-info → gammasimtools-0.25.0.dist-info}/METADATA +1 -1
  2. {gammasimtools-0.24.0.dist-info → gammasimtools-0.25.0.dist-info}/RECORD +58 -55
  3. {gammasimtools-0.24.0.dist-info → gammasimtools-0.25.0.dist-info}/entry_points.txt +1 -0
  4. simtools/_version.py +2 -2
  5. simtools/application_control.py +50 -0
  6. simtools/applications/derive_psf_parameters.py +5 -0
  7. simtools/applications/derive_pulse_shape_parameters.py +195 -0
  8. simtools/applications/plot_array_layout.py +63 -1
  9. simtools/applications/simulate_flasher.py +3 -2
  10. simtools/applications/simulate_pedestals.py +1 -1
  11. simtools/applications/simulate_prod.py +8 -23
  12. simtools/applications/simulate_prod_htcondor_generator.py +7 -0
  13. simtools/applications/submit_array_layouts.py +5 -3
  14. simtools/applications/validate_file_using_schema.py +49 -123
  15. simtools/configuration/commandline_parser.py +8 -6
  16. simtools/corsika/corsika_config.py +197 -87
  17. simtools/data_model/model_data_writer.py +14 -2
  18. simtools/data_model/schema.py +112 -5
  19. simtools/data_model/validate_data.py +82 -48
  20. simtools/db/db_model_upload.py +2 -1
  21. simtools/db/mongo_db.py +133 -42
  22. simtools/dependencies.py +5 -9
  23. simtools/io/eventio_handler.py +128 -0
  24. simtools/job_execution/htcondor_script_generator.py +0 -2
  25. simtools/layout/array_layout_utils.py +1 -1
  26. simtools/model/array_model.py +36 -5
  27. simtools/model/model_parameter.py +0 -1
  28. simtools/model/model_repository.py +18 -5
  29. simtools/ray_tracing/psf_analysis.py +11 -8
  30. simtools/ray_tracing/psf_parameter_optimisation.py +822 -679
  31. simtools/reporting/docs_read_parameters.py +69 -9
  32. simtools/runners/corsika_runner.py +12 -3
  33. simtools/runners/corsika_simtel_runner.py +6 -0
  34. simtools/runners/runner_services.py +17 -7
  35. simtools/runners/simtel_runner.py +12 -54
  36. simtools/schemas/model_parameters/flasher_pulse_exp_decay.schema.yml +2 -0
  37. simtools/schemas/model_parameters/flasher_pulse_shape.schema.yml +50 -0
  38. simtools/schemas/model_parameters/flasher_pulse_width.schema.yml +2 -0
  39. simtools/schemas/simulation_models_info.schema.yml +2 -0
  40. simtools/simtel/pulse_shapes.py +268 -0
  41. simtools/simtel/simtel_config_writer.py +82 -1
  42. simtools/simtel/simtel_io_event_writer.py +2 -2
  43. simtools/simtel/simulator_array.py +58 -12
  44. simtools/simtel/simulator_light_emission.py +45 -8
  45. simtools/simulator.py +361 -347
  46. simtools/testing/assertions.py +62 -6
  47. simtools/testing/configuration.py +1 -1
  48. simtools/testing/log_inspector.py +4 -1
  49. simtools/testing/sim_telarray_metadata.py +1 -1
  50. simtools/testing/validate_output.py +44 -9
  51. simtools/utils/names.py +2 -4
  52. simtools/version.py +37 -0
  53. simtools/visualization/legend_handlers.py +14 -4
  54. simtools/visualization/plot_array_layout.py +229 -33
  55. simtools/visualization/plot_mirrors.py +837 -0
  56. simtools/simtel/simtel_io_file_info.py +0 -62
  57. {gammasimtools-0.24.0.dist-info → gammasimtools-0.25.0.dist-info}/WHEEL +0 -0
  58. {gammasimtools-0.24.0.dist-info → gammasimtools-0.25.0.dist-info}/licenses/LICENSE +0 -0
  59. {gammasimtools-0.24.0.dist-info → gammasimtools-0.25.0.dist-info}/top_level.txt +0 -0
@@ -36,8 +36,6 @@ class ArrayModel:
36
36
  the array element positions).
37
37
  calibration_device_types: List[str], optional
38
38
  List of calibration device types (e.g., 'flat_fielding') attached to each telescope.
39
- sim_telarray_seeds : dict, optional
40
- Dictionary with configuration for sim_telarray random instrument setup.
41
39
  simtel_path: str, Path, optional
42
40
  Path to the sim_telarray installation directory.
43
41
  overwrite_model_parameters: str, optional
@@ -53,7 +51,6 @@ class ArrayModel:
53
51
  layout_name=None,
54
52
  array_elements=None,
55
53
  calibration_device_types=None,
56
- sim_telarray_seeds=None,
57
54
  simtel_path=None,
58
55
  overwrite_model_parameters=None,
59
56
  ):
@@ -80,7 +77,7 @@ class ArrayModel:
80
77
 
81
78
  self._telescope_model_files_exported = False
82
79
  self._array_model_file_exported = False
83
- self.sim_telarray_seeds = sim_telarray_seeds
80
+ self._sim_telarray_seeds = None
84
81
  self.simtel_path = simtel_path
85
82
 
86
83
  def _initialize(self, site, array_elements_config, calibration_device_types):
@@ -139,6 +136,41 @@ class ArrayModel:
139
136
 
140
137
  return array_elements, site_model, telescope_models, calibration_models
141
138
 
139
+ @property
140
+ def sim_telarray_seeds(self):
141
+ """
142
+ Return sim_telarray seeds.
143
+
144
+ Returns
145
+ -------
146
+ dict
147
+ Dictionary with sim_telarray seeds.
148
+ """
149
+ return self._sim_telarray_seeds
150
+
151
+ @sim_telarray_seeds.setter
152
+ def sim_telarray_seeds(self, value):
153
+ """
154
+ Set sim_telarray seeds.
155
+
156
+ Parameters
157
+ ----------
158
+ value: dict
159
+ Dictionary with sim_telarray seeds.
160
+ """
161
+ if isinstance(value, dict):
162
+ required_keys = {
163
+ "seed",
164
+ "random_instrument_instances",
165
+ "seed_file_name",
166
+ }
167
+ if not required_keys.issubset(value):
168
+ raise ValueError(
169
+ "sim_telarray_seeds dictionary must contain the following keys: "
170
+ f"{required_keys}"
171
+ )
172
+ self._sim_telarray_seeds = value
173
+
142
174
  @property
143
175
  def config_file_path(self):
144
176
  """
@@ -153,7 +185,6 @@ class ArrayModel:
153
185
  config_file_name = names.simtel_config_file_name(
154
186
  array_name=self.layout_name,
155
187
  site=self.site_model.site,
156
- model_version=self.model_version,
157
188
  label=self.label,
158
189
  )
159
190
  self._config_file_path = self.get_config_directory().joinpath(config_file_name)
@@ -271,7 +271,6 @@ class ModelParameter:
271
271
  # Setting file name and the location
272
272
  config_file_name = names.simtel_config_file_name(
273
273
  self.site,
274
- self.model_version,
275
274
  telescope_model_name=self.name,
276
275
  label=self.label,
277
276
  )
@@ -361,7 +361,7 @@ def _get_changes_to_production(
361
361
  _version_changes, base_model_version = _get_changes_to_production(
362
362
  _changes_dict, simulation_models_path, update_type="full_update"
363
363
  )
364
- changes = _update_two_levels_in_changes_dict(changes, _version_changes)
364
+ changes = _update_two_levels_in_changes_dict(_version_changes, changes)
365
365
  # stop iterative loop after reaching first full version of production tables
366
366
  if _changes_dict.get("model_update", "full_update") == "full_update":
367
367
  break
@@ -461,7 +461,7 @@ def _create_new_model_parameter_entry(telescope, param, param_data, simulation_m
461
461
 
462
462
  param_dir = telescope_dir / param
463
463
  try:
464
- latest_file = _get_latest_model_parameter_file(param_dir, param)
464
+ latest_file = _get_latest_model_parameter_file(param_dir, param, param_data["version"])
465
465
  except FileNotFoundError:
466
466
  latest_file = None
467
467
 
@@ -484,10 +484,11 @@ def _create_new_model_parameter_entry(telescope, param, param_data, simulation_m
484
484
  output_path=param_dir,
485
485
  unit=param_data.get("unit"),
486
486
  meta_parameter=param_data.get("meta_parameter", False),
487
+ model_parameter_schema_version=param_data.get("model_parameter_schema_version", None),
487
488
  )
488
489
 
489
490
 
490
- def _get_latest_model_parameter_file(directory, parameter):
491
+ def _get_latest_model_parameter_file(directory, parameter, max_version):
491
492
  """
492
493
  Get the latest model parameter JSON file for a parameter in the given directory.
493
494
 
@@ -499,11 +500,14 @@ def _get_latest_model_parameter_file(directory, parameter):
499
500
  Path to the directory containing parameter JSON files.
500
501
  parameter: str
501
502
  Name of the parameter to find.
503
+ max_version: str
504
+ Maximum version to consider (inclusive). Files with versions greater than
505
+ this will be excluded.
502
506
 
503
507
  Returns
504
508
  -------
505
509
  str
506
- Path to the latest JSON file for the parameter.
510
+ Path to the latest JSON file for the parameter with version <= max_version.
507
511
 
508
512
  Raises
509
513
  ------
@@ -521,7 +525,16 @@ def _get_latest_model_parameter_file(directory, parameter):
521
525
  # version is part after first '-'
522
526
  return parse_version(path.stem.split("-", 1)[1])
523
527
 
524
- latest_file = max(files, key=extract_version)
528
+ max_ver = parse_version(max_version)
529
+ filtered_files = [f for f in files if extract_version(f) <= max_ver]
530
+
531
+ if not filtered_files:
532
+ raise FileNotFoundError(
533
+ f"No JSON files found for parameter '{parameter}' with version <= {max_version} "
534
+ f"in directory '{directory}'."
535
+ )
536
+
537
+ latest_file = max(filtered_files, key=extract_version)
525
538
  return str(latest_file)
526
539
 
527
540
 
@@ -516,18 +516,21 @@ class PSFImage:
516
516
 
517
517
  Parameters
518
518
  ----------
519
+ file_name: str
520
+ Name of the file to save the plot to.
521
+ d80: float
522
+ d80 value to be marked in the plot (in cm).
519
523
  **kwargs:
520
- image_* for the histogram plot and psf_* for the psf circle.
524
+ Customization of line plot (e.g., color, linestyle, linewidth).
521
525
  """
522
526
  data = self.get_cumulative_data()
523
- ax = plt.gca()
524
- plt.tight_layout(pad=1.5)
527
+ fig, ax = plt.subplots(constrained_layout=True)
525
528
  ax.set_xlabel("Radius (cm)")
526
529
  ax.set_ylabel("Contained light %")
527
- plt.plot(data[self.__PSF_RADIUS], data[self.__PSF_CUMULATIVE], **kwargs)
528
- plt.axvline(x=self.get_psf(0.8) / 2, color="b", linestyle="--", linewidth=1)
530
+ ax.plot(data[self.__PSF_RADIUS], data[self.__PSF_CUMULATIVE], **kwargs)
531
+ ax.axvline(x=self.get_psf(0.8) / 2, color="b", linestyle="--", linewidth=1)
529
532
  if d80 is not None:
530
- plt.axvline(x=d80 / 2.0, color="r", linestyle="--", linewidth=1)
533
+ ax.axvline(x=d80 / 2.0, color="r", linestyle="--", linewidth=1)
531
534
  if file_name is not None:
532
- plt.savefig(file_name)
533
- plt.close()
535
+ fig.savefig(file_name)
536
+ plt.close(fig)