gammasimtools 0.24.0__py3-none-any.whl → 0.26.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 (138) hide show
  1. {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/METADATA +2 -1
  2. {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/RECORD +134 -130
  3. {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/entry_points.txt +3 -1
  4. {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/licenses/LICENSE +1 -1
  5. simtools/_version.py +2 -2
  6. simtools/application_control.py +78 -0
  7. simtools/applications/calculate_incident_angles.py +0 -2
  8. simtools/applications/convert_geo_coordinates_of_array_elements.py +1 -2
  9. simtools/applications/db_add_file_to_db.py +1 -1
  10. simtools/applications/db_add_simulation_model_from_repository_to_db.py +1 -1
  11. simtools/applications/db_add_value_from_json_to_db.py +1 -1
  12. simtools/applications/db_generate_compound_indexes.py +1 -1
  13. simtools/applications/db_get_array_layouts_from_db.py +2 -6
  14. simtools/applications/db_get_file_from_db.py +1 -1
  15. simtools/applications/db_get_parameter_from_db.py +1 -1
  16. simtools/applications/db_inspect_databases.py +1 -1
  17. simtools/applications/db_upload_model_repository.py +1 -1
  18. simtools/applications/derive_ctao_array_layouts.py +1 -2
  19. simtools/applications/derive_mirror_rnda.py +1 -3
  20. simtools/applications/derive_psf_parameters.py +5 -1
  21. simtools/applications/derive_pulse_shape_parameters.py +194 -0
  22. simtools/applications/derive_trigger_rates.py +1 -1
  23. simtools/applications/docs_produce_array_element_report.py +2 -8
  24. simtools/applications/docs_produce_calibration_reports.py +1 -3
  25. simtools/applications/docs_produce_model_parameter_reports.py +0 -2
  26. simtools/applications/docs_produce_simulation_configuration_report.py +1 -3
  27. simtools/applications/generate_array_config.py +0 -1
  28. simtools/applications/generate_corsika_histograms.py +48 -235
  29. simtools/applications/generate_regular_arrays.py +5 -35
  30. simtools/applications/generate_simtel_event_data.py +2 -2
  31. simtools/applications/maintain_simulation_model_add_production.py +2 -2
  32. simtools/applications/maintain_simulation_model_write_array_element_positions.py +87 -0
  33. simtools/applications/plot_array_layout.py +64 -108
  34. simtools/applications/plot_simulated_event_distributions.py +57 -0
  35. simtools/applications/plot_tabular_data.py +0 -1
  36. simtools/applications/plot_tabular_data_for_model_parameter.py +1 -6
  37. simtools/applications/production_derive_corsika_limits.py +1 -1
  38. simtools/applications/production_generate_grid.py +0 -1
  39. simtools/applications/run_application.py +1 -1
  40. simtools/applications/simulate_flasher.py +3 -4
  41. simtools/applications/simulate_illuminator.py +0 -1
  42. simtools/applications/simulate_pedestals.py +2 -6
  43. simtools/applications/simulate_prod.py +9 -28
  44. simtools/applications/simulate_prod_htcondor_generator.py +8 -1
  45. simtools/applications/submit_array_layouts.py +7 -7
  46. simtools/applications/submit_model_parameter_from_external.py +1 -3
  47. simtools/applications/validate_camera_efficiency.py +0 -1
  48. simtools/applications/validate_camera_fov.py +0 -1
  49. simtools/applications/validate_cumulative_psf.py +0 -2
  50. simtools/applications/validate_file_using_schema.py +49 -123
  51. simtools/applications/validate_optics.py +0 -13
  52. simtools/camera/camera_efficiency.py +1 -6
  53. simtools/camera/single_photon_electron_spectrum.py +2 -1
  54. simtools/configuration/commandline_parser.py +43 -8
  55. simtools/configuration/configurator.py +6 -11
  56. simtools/corsika/corsika_config.py +204 -99
  57. simtools/corsika/corsika_histograms.py +411 -1735
  58. simtools/corsika/primary_particle.py +1 -1
  59. simtools/data_model/metadata_collector.py +5 -2
  60. simtools/data_model/metadata_model.py +0 -4
  61. simtools/data_model/model_data_writer.py +27 -17
  62. simtools/data_model/schema.py +112 -5
  63. simtools/data_model/validate_data.py +80 -48
  64. simtools/db/db_handler.py +19 -8
  65. simtools/db/db_model_upload.py +2 -1
  66. simtools/db/mongo_db.py +133 -42
  67. simtools/dependencies.py +83 -44
  68. simtools/io/ascii_handler.py +4 -2
  69. simtools/io/table_handler.py +1 -1
  70. simtools/job_execution/htcondor_script_generator.py +0 -2
  71. simtools/layout/array_layout.py +4 -12
  72. simtools/layout/array_layout_utils.py +227 -58
  73. simtools/model/array_model.py +37 -18
  74. simtools/model/calibration_model.py +0 -4
  75. simtools/model/legacy_model_parameter.py +134 -0
  76. simtools/model/model_parameter.py +24 -14
  77. simtools/model/model_repository.py +18 -5
  78. simtools/model/model_utils.py +1 -6
  79. simtools/model/site_model.py +0 -4
  80. simtools/model/telescope_model.py +6 -11
  81. simtools/production_configuration/derive_corsika_limits.py +6 -11
  82. simtools/production_configuration/interpolation_handler.py +16 -16
  83. simtools/ray_tracing/incident_angles.py +5 -11
  84. simtools/ray_tracing/mirror_panel_psf.py +3 -7
  85. simtools/ray_tracing/psf_analysis.py +29 -27
  86. simtools/ray_tracing/psf_parameter_optimisation.py +822 -680
  87. simtools/ray_tracing/ray_tracing.py +6 -15
  88. simtools/reporting/docs_auto_report_generator.py +8 -13
  89. simtools/reporting/docs_read_parameters.py +70 -16
  90. simtools/runners/corsika_runner.py +15 -10
  91. simtools/runners/corsika_simtel_runner.py +9 -8
  92. simtools/runners/runner_services.py +17 -7
  93. simtools/runners/simtel_runner.py +11 -58
  94. simtools/runners/simtools_runner.py +2 -4
  95. simtools/schemas/model_parameters/flasher_pulse_exp_decay.schema.yml +2 -0
  96. simtools/schemas/model_parameters/flasher_pulse_shape.schema.yml +50 -0
  97. simtools/schemas/model_parameters/flasher_pulse_width.schema.yml +2 -0
  98. simtools/schemas/simulation_models_info.schema.yml +2 -0
  99. simtools/settings.py +154 -0
  100. simtools/sim_events/file_info.py +128 -0
  101. simtools/{simtel/simtel_io_event_histograms.py → sim_events/histograms.py} +25 -15
  102. simtools/{simtel/simtel_io_event_reader.py → sim_events/reader.py} +20 -17
  103. simtools/{simtel/simtel_io_event_writer.py → sim_events/writer.py} +84 -25
  104. simtools/simtel/pulse_shapes.py +273 -0
  105. simtools/simtel/simtel_config_writer.py +146 -22
  106. simtools/simtel/simtel_table_reader.py +6 -4
  107. simtools/simtel/simulator_array.py +62 -23
  108. simtools/simtel/simulator_camera_efficiency.py +4 -6
  109. simtools/simtel/simulator_light_emission.py +101 -19
  110. simtools/simtel/simulator_ray_tracing.py +4 -10
  111. simtools/simulator.py +360 -353
  112. simtools/telescope_trigger_rates.py +3 -4
  113. simtools/testing/assertions.py +115 -8
  114. simtools/testing/configuration.py +2 -3
  115. simtools/testing/helpers.py +2 -3
  116. simtools/testing/log_inspector.py +5 -1
  117. simtools/testing/sim_telarray_metadata.py +1 -1
  118. simtools/testing/validate_output.py +69 -23
  119. simtools/utils/general.py +37 -0
  120. simtools/utils/geometry.py +0 -77
  121. simtools/utils/names.py +7 -9
  122. simtools/version.py +37 -0
  123. simtools/visualization/legend_handlers.py +21 -10
  124. simtools/visualization/plot_array_layout.py +312 -41
  125. simtools/visualization/plot_corsika_histograms.py +143 -605
  126. simtools/visualization/plot_mirrors.py +834 -0
  127. simtools/visualization/plot_pixels.py +2 -4
  128. simtools/visualization/plot_psf.py +0 -1
  129. simtools/visualization/plot_simtel_event_histograms.py +4 -4
  130. simtools/visualization/plot_simtel_events.py +6 -11
  131. simtools/visualization/plot_tables.py +8 -19
  132. simtools/visualization/visualize.py +22 -2
  133. simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +0 -160
  134. simtools/applications/print_version.py +0 -53
  135. simtools/io/hdf5_handler.py +0 -139
  136. simtools/simtel/simtel_io_file_info.py +0 -62
  137. {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/WHEEL +0 -0
  138. {gammasimtools-0.24.0.dist-info → gammasimtools-0.26.0.dist-info}/top_level.txt +0 -0
@@ -21,7 +21,7 @@ from simtools.visualization import visualize
21
21
  logger = logging.getLogger(__name__)
22
22
 
23
23
 
24
- def plot(config, output_file, db_config=None):
24
+ def plot(config, output_file):
25
25
  """
26
26
  Plot pixel layout based on configuration.
27
27
 
@@ -36,15 +36,13 @@ def plot(config, output_file, db_config=None):
36
36
  - telescope : str, name of the telescope
37
37
  output_file : str
38
38
  Path where to save the plot
39
- db_config : dict, optional
40
- Database configuration.
41
39
 
42
40
  Returns
43
41
  -------
44
42
  None
45
43
  The function saves the plot to the specified output file.
46
44
  """
47
- db = db_handler.DatabaseHandler(db_config=db_config)
45
+ db = db_handler.DatabaseHandler()
48
46
  db.export_model_file(
49
47
  parameter=config["parameter"],
50
48
  site=config["site"],
@@ -654,7 +654,6 @@ def create_psf_vs_offaxis_plot(tel_model, site_model, args_dict, best_pars, outp
654
654
  ray = RayTracing(
655
655
  telescope_model=tel_model,
656
656
  site_model=site_model,
657
- simtel_path=args_dict["simtel_path"],
658
657
  zenith_angle=args_dict["zenith"] * u.deg,
659
658
  source_distance=args_dict["src_distance"] * u.km,
660
659
  off_axis_angle=off_axis_angles * u.deg,
@@ -1,4 +1,4 @@
1
- """Plot simtel event histograms filled with SimtelIOEventHistograms."""
1
+ """Plot simtel event histograms filled with EventDataHistograms."""
2
2
 
3
3
  import logging
4
4
 
@@ -6,7 +6,7 @@ import matplotlib.pyplot as plt
6
6
  import numpy as np
7
7
  from matplotlib.colors import LogNorm
8
8
 
9
- from simtools.simtel.simtel_io_event_histograms import SimtelIOEventHistograms
9
+ from simtools.sim_events.histograms import EventDataHistograms
10
10
 
11
11
  _logger = logging.getLogger(__name__)
12
12
 
@@ -17,7 +17,7 @@ def plot(histograms, output_path=None, limits=None, rebin_factor=2, array_name=N
17
17
 
18
18
  Parameters
19
19
  ----------
20
- histograms: SimtelIOEventHistograms
20
+ histograms: EventDataHistograms
21
21
  Instance containing the histograms to plot.
22
22
  output_path: Path or str, optional
23
23
  Directory to save plots. If None, plots will be displayed.
@@ -230,7 +230,7 @@ def _create_rebinned_plot(plot_args, filename, output_path, rebin_factor):
230
230
  data = plot_args["data"]
231
231
  bins = plot_args["bins"]
232
232
 
233
- rebinned_data, rebinned_x_bins, rebinned_y_bins = SimtelIOEventHistograms.rebin_2d_histogram(
233
+ rebinned_data, rebinned_x_bins, rebinned_y_bins = EventDataHistograms.rebin_2d_histogram(
234
234
  data, bins[0], bins[1], rebin_factor
235
235
  )
236
236
 
@@ -13,8 +13,7 @@ from ctapipe.visualization import CameraDisplay
13
13
  from scipy import signal as _signal
14
14
 
15
15
  from simtools.data_model.metadata_collector import MetadataCollector
16
- from simtools.visualization.plot_corsika_histograms import save_figs_to_pdf
17
- from simtools.visualization.visualize import save_figure
16
+ from simtools.visualization.visualize import save_figure, save_figures_to_single_document
18
17
 
19
18
  _logger = logging.getLogger(__name__)
20
19
 
@@ -665,24 +664,21 @@ def plot_simtel_peak_timing(
665
664
 
666
665
  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4), dpi=300)
667
666
 
668
- edges = _histogram_edges(n_samp, timing_bins)
669
- et_name = getattr(getattr(event.trigger, "event_type", None), "name", "?")
670
667
  tel = source.subarray.tel[tel_id]
671
668
  tel_label = getattr(tel, "name", f"CT{tel_id}")
672
669
  _draw_peak_hist(
673
670
  ax1,
674
671
  peak_samples,
675
- edges,
672
+ _histogram_edges(n_samp, timing_bins),
676
673
  mean_sample,
677
674
  std_sample,
678
675
  tel_label,
679
- et_name,
676
+ getattr(getattr(event.trigger, "event_type", None), "name", "?"),
680
677
  pix_ids.size,
681
678
  found_count,
682
679
  )
683
680
 
684
- readout = source.subarray.tel[tel_id].camera.readout
685
- t = _time_axis_from_readout(readout, n_samp)
681
+ t = _time_axis_from_readout(source.subarray.tel[tel_id].camera.readout, n_samp)
686
682
 
687
683
  ex_ids = pix_ids[: max(1, int(examples))]
688
684
  for pid in ex_ids:
@@ -698,13 +694,12 @@ def plot_simtel_peak_timing(
698
694
  fig.tight_layout()
699
695
 
700
696
  if return_stats:
701
- stats = {
697
+ return fig, {
702
698
  "considered": int(pix_ids.size),
703
699
  "found": int(found_count),
704
700
  "mean": float(mean_sample),
705
701
  "std": float(std_sample),
706
702
  }
707
- return fig, stats
708
703
  return fig
709
704
 
710
705
 
@@ -991,7 +986,7 @@ def generate_and_save_plots(
991
986
  continue
992
987
 
993
988
  try:
994
- save_figs_to_pdf(figures, pdf_path)
989
+ save_figures_to_single_document(figures, pdf_path)
995
990
  _logger.info("Saved PDF: %s", pdf_path)
996
991
  except Exception as ex: # pylint:disable=broad-except
997
992
  _logger.error("Failed to save PDF %s: %s", pdf_path, ex)
@@ -16,7 +16,7 @@ from simtools.visualization import visualize
16
16
  _logger = logging.getLogger(__name__)
17
17
 
18
18
 
19
- def plot(config, output_file, db_config=None, data_path=None):
19
+ def plot(config, output_file, data_path=None):
20
20
  """
21
21
  Plot tabular data from data or from model parameter files.
22
22
 
@@ -26,12 +26,10 @@ def plot(config, output_file, db_config=None, data_path=None):
26
26
  Configuration dictionary for plotting.
27
27
  output_file: str
28
28
  Output file.
29
- db_config: dict, optional
30
- Database configuration dictionary for accessing the model parameter database.
31
29
  data_path: Path or str, optional
32
30
  Path to the data files (optional). Expect all files to be in the same directory.
33
31
  """
34
- data = read_table_data(config, db_config, data_path)
32
+ data = read_table_data(config, data_path)
35
33
 
36
34
  fig = visualize.plot_1d(
37
35
  data,
@@ -42,7 +40,7 @@ def plot(config, output_file, db_config=None, data_path=None):
42
40
  return output_file
43
41
 
44
42
 
45
- def read_table_data(config, db_config, data_path=None):
43
+ def read_table_data(config, data_path=None):
46
44
  """
47
45
  Read table data from file or parameter database.
48
46
 
@@ -50,8 +48,6 @@ def read_table_data(config, db_config, data_path=None):
50
48
  ----------
51
49
  config: dict
52
50
  Configuration dictionary for plotting.
53
- db_config: dict
54
- Database configuration dictionary for accessing the model parameter database.
55
51
  data_path: Path or str, optional
56
52
  Path to the data files (optional). Expect all files to be in the same directory.
57
53
 
@@ -64,7 +60,7 @@ def read_table_data(config, db_config, data_path=None):
64
60
 
65
61
  for _config in config["tables"]:
66
62
  if "parameter" in _config:
67
- table = _read_table_from_model_database(_config, db_config)
63
+ table = _read_table_from_model_database(_config)
68
64
  elif "file_name" in _config:
69
65
  file_name = (
70
66
  _config["file_name"]
@@ -117,7 +113,7 @@ def _process_table_data(table, _config):
117
113
  )
118
114
 
119
115
 
120
- def _read_table_from_model_database(table_config, db_config):
116
+ def _read_table_from_model_database(table_config):
121
117
  """
122
118
  Read table data from model parameter database.
123
119
 
@@ -131,7 +127,7 @@ def _read_table_from_model_database(table_config, db_config):
131
127
  Table
132
128
  Astropy table
133
129
  """
134
- db = db_handler.DatabaseHandler(db_config=db_config)
130
+ db = db_handler.DatabaseHandler()
135
131
  return db.export_model_file(
136
132
  parameter=table_config["parameter"],
137
133
  site=table_config["site"],
@@ -170,15 +166,11 @@ def _validate_config_columns(config, valid_columns, logger):
170
166
 
171
167
  def _get_valid_columns(table):
172
168
  """Return columns that exist and have valid data (not all NaN)."""
173
- valid_columns = []
174
- for col in table.colnames:
175
- if not all(np.isnan(table[col])):
176
- valid_columns.append(col)
177
- return valid_columns
169
+ return [col for col in table.colnames if not all(np.isnan(table[col]))]
178
170
 
179
171
 
180
172
  def generate_plot_configurations(
181
- parameter, parameter_version, site, telescope, output_path, plot_type, db_config
173
+ parameter, parameter_version, site, telescope, output_path, plot_type
182
174
  ):
183
175
  """
184
176
  Generate plot configurations for a model parameter from schema files.
@@ -197,8 +189,6 @@ def generate_plot_configurations(
197
189
  Output path for the plots.
198
190
  plot_type: str
199
191
  Plot type or "all" for all plots.
200
- db_config: dict
201
- Database configuration.
202
192
 
203
193
  Returns
204
194
  -------
@@ -226,7 +216,6 @@ def generate_plot_configurations(
226
216
  "telescope": telescope,
227
217
  "parameter_version": parameter_version,
228
218
  },
229
- db_config=db_config,
230
219
  )
231
220
  valid_columns = _get_valid_columns(table)
232
221
 
@@ -11,6 +11,7 @@ import matplotlib.pyplot as plt
11
11
  from astropy.table import QTable
12
12
  from cycler import cycler
13
13
  from matplotlib import gridspec
14
+ from matplotlib.backends.backend_pdf import PdfPages
14
15
 
15
16
  COLORS = {}
16
17
  COLORS["classic"] = [
@@ -615,7 +616,7 @@ def plot_hist_2d(data, **kwargs):
615
616
  return fig
616
617
 
617
618
 
618
- def save_figure(fig, output_file, figure_format=None, log_title="", dpi="figure"):
619
+ def save_figure(fig, output_file, figure_format=("pdf", "png"), log_title="", dpi="figure"):
619
620
  """
620
621
  Save figure to output file(s).
621
622
 
@@ -630,10 +631,29 @@ def save_figure(fig, output_file, figure_format=None, log_title="", dpi="figure"
630
631
  title: str
631
632
  Title of the figure to be added to the log message.
632
633
  """
633
- figure_format = figure_format or ["pdf", "png"]
634
634
  for fmt in figure_format:
635
635
  _file = Path(output_file).with_suffix(f".{fmt}")
636
636
  fig.savefig(_file, format=fmt, bbox_inches="tight", dpi=dpi)
637
637
  logging.info(f"Saved plot {log_title} to {_file}")
638
638
 
639
639
  fig.clf()
640
+
641
+
642
+ def save_figures_to_single_document(figs, output_file_name):
643
+ """
644
+ Save multiple figures to a single PDF document.
645
+
646
+ Parameters
647
+ ----------
648
+ figs: list
649
+ List of plt.figure instances to save.
650
+ output_file_name: Path, str
651
+ PDF file name
652
+ """
653
+ _logger.info(f"Saving {len(figs)} figures to {output_file_name}")
654
+ pdf_pages = PdfPages(Path(output_file_name).absolute().as_posix())
655
+ for fig in figs:
656
+ plt.tight_layout()
657
+ pdf_pages.savefig(fig)
658
+
659
+ pdf_pages.close()
@@ -1,160 +0,0 @@
1
- #!/usr/bin/python3
2
- """
3
- Read array element positions from file and add them to model repository.
4
-
5
- This is an application for experts and should not be used by the general user.
6
- Reading of input is fine-tuned to the array element files as provided by CTAO.
7
-
8
- Command line arguments
9
-
10
- input : str
11
- File containing a table of array element positions.
12
- repository_path : str
13
- Path of local copy of model parameter repository.
14
- parameter_version : str
15
- Parameter version.
16
- site : str
17
- Observatory site.
18
- coordinate_system : str
19
- Coordinate system of array element positions (ground or utm).
20
-
21
- Examples
22
- --------
23
- Add array element positions to repository:
24
-
25
- .. code-block:: console
26
-
27
- simtools-write-array-element-positions-to-repository \
28
- --input /path/to/positions.txt \
29
- --repository_path /path/to/repository \
30
- --parameter_version 0.1.0 \
31
- --coordinate_system ground \
32
- --site North
33
-
34
- """
35
-
36
- from pathlib import Path
37
-
38
- import astropy.table
39
-
40
- from simtools.application_control import get_application_label, startup_application
41
- from simtools.configuration import configurator
42
- from simtools.data_model.model_data_writer import ModelDataWriter
43
- from simtools.io import ascii_handler
44
- from simtools.model.array_model import ArrayModel
45
-
46
-
47
- def _parse():
48
- """Parse command line configuration."""
49
- config = configurator.Configurator(
50
- label=get_application_label(__file__),
51
- description="Add array element positions to model parameter repository",
52
- )
53
- config.parser.add_argument(
54
- "--input",
55
- help="File containing a table of array element positions.",
56
- required=False,
57
- )
58
- config.parser.add_argument(
59
- "--repository_path",
60
- help="Output path to model parameter repository.",
61
- type=Path,
62
- required=False,
63
- )
64
- config.parser.add_argument(
65
- "--coordinate_system",
66
- help="Coordinate system of array element positions (utm or ground).",
67
- default="ground",
68
- required=False,
69
- type=str,
70
- choices=["ground", "utm"],
71
- )
72
-
73
- return config.initialize(db_config=True, simulation_model=["site", "parameter_version"])
74
-
75
-
76
- def write_utm_array_elements_to_repository(args_dict, logger):
77
- """
78
- Write UTM position of array elements to model repository.
79
-
80
- Read array element positions from file. The ecsv row definition might
81
- include telescope_name or asset_code and sequence_number.
82
-
83
- Parameters
84
- ----------
85
- args_dict : dict
86
- Command line arguments.
87
- app_context.logger : app_context.logger
88
- app_context.logger object.
89
-
90
- """
91
- array_elements = astropy.table.Table.read(args_dict["input"])
92
- for row in array_elements:
93
- instrument = (
94
- row["telescope_name"]
95
- if "telescope_name" in array_elements.colnames
96
- else f"{row['asset_code']}-{row['sequence_number']}"
97
- )
98
- output_path = Path(args_dict["repository_path"]) / f"{instrument}"
99
- output_path.mkdir(parents=True, exist_ok=True)
100
- logger.info(f"Writing array element positions (utm) to {output_path}")
101
-
102
- ModelDataWriter.dump_model_parameter(
103
- parameter_name="array_element_position_utm",
104
- instrument=instrument,
105
- value=f"{row['utm_east']} {row['utm_north']} {row['altitude']}",
106
- parameter_version=args_dict["parameter_version"],
107
- output_path=output_path,
108
- output_file="array_element_position_utm.json",
109
- )
110
-
111
-
112
- def write_ground_array_elements_to_repository(args_dict, db_config, logger):
113
- """
114
- Write ground position of array elements to model repository.
115
-
116
- Parameters
117
- ----------
118
- args_dict : dict
119
- Command line arguments.
120
- db_config : dict
121
- Database configuration.
122
- logger : logger
123
- logger object.
124
-
125
- """
126
- array_model = ArrayModel(
127
- db_config=db_config,
128
- model_version=None,
129
- site=args_dict["site"],
130
- array_elements=args_dict["input"],
131
- )
132
- for element_name, data in array_model.array_elements.items():
133
- output_path = Path(args_dict["repository_path"]) / f"{element_name}"
134
- output_path.mkdir(parents=True, exist_ok=True)
135
- logger.info(f"Writing array element positions (ground) to {output_path}")
136
- ascii_handler.write_data_to_file(
137
- data=data,
138
- output_file=output_path / "array_element_position_ground.json",
139
- sort_keys=False,
140
- numpy_types=True,
141
- )
142
-
143
-
144
- def main():
145
- """Application main."""
146
- app_context = startup_application(_parse)
147
-
148
- if app_context.args["coordinate_system"] == "utm":
149
- write_utm_array_elements_to_repository(app_context.args, app_context.logger)
150
- elif app_context.args["coordinate_system"] == "ground":
151
- write_ground_array_elements_to_repository(
152
- app_context.args, app_context.db_config, app_context.logger
153
- )
154
- else:
155
- app_context.logger.error("Invalid coordinate system. Allowed are 'utm' and 'ground'.")
156
- raise ValueError
157
-
158
-
159
- if __name__ == "__main__":
160
- main()
@@ -1,53 +0,0 @@
1
- #!/usr/bin/python3
2
- """
3
- Print the versions of the simtools software.
4
-
5
- The versions of simtools, the DB, sim_telarray, and CORSIKA are printed.
6
-
7
- """
8
-
9
- from simtools import dependencies, version
10
- from simtools.application_control import get_application_label, startup_application
11
- from simtools.configuration import configurator
12
- from simtools.io import ascii_handler
13
-
14
-
15
- def _parse():
16
- """Parse command line configuration."""
17
- config = configurator.Configurator(
18
- label=get_application_label(__file__),
19
- description="Print the versions of simtools, the DB, sim_telarray and CORSIKA.",
20
- usage="simtools-print-version",
21
- )
22
- return config.initialize(db_config=True, output=True, require_command_line=False)
23
-
24
-
25
- def main():
26
- """Print the versions of the simtools software."""
27
- app_context = startup_application(_parse)
28
-
29
- version_string = dependencies.get_version_string(app_context.db_config)
30
- version_dict = {"simtools version": version.__version__}
31
-
32
- print()
33
- # The loop below is not necessary, there is only one entry, but it is cleaner
34
- for key, value in version_dict.items(): #
35
- print(f"{key}: {value}")
36
- print(version_string)
37
-
38
- version_list = version_string.strip().split("\n")
39
- for version_entry in version_list:
40
- key, value = version_entry.split(": ", 1)
41
- version_dict[key] = value
42
-
43
- if not app_context.args.get("output_file_from_default", False):
44
- ascii_handler.write_data_to_file(
45
- data=version_dict,
46
- output_file=app_context.io_handler.get_output_file(
47
- app_context.args.get("output_file", "simtools_version.json")
48
- ),
49
- )
50
-
51
-
52
- if __name__ == "__main__":
53
- main()
@@ -1,139 +0,0 @@
1
- """Helper module for reading and writing in hd5 format."""
2
-
3
- import logging
4
- from pathlib import PosixPath
5
-
6
- import astropy.units as u
7
- import tables
8
- from astropy.table import Table
9
- from ctapipe.io import read_table
10
-
11
- from simtools.utils.names import sanitize_name
12
-
13
- _logger = logging.getLogger(__name__)
14
-
15
-
16
- def fill_hdf5_table(hist, x_bin_edges, y_bin_edges, x_label, y_label, meta_data):
17
- """
18
- Create and fill an hdf5 table with the histogram information.
19
-
20
- It works for both 1D and 2D distributions.
21
-
22
- Parameters
23
- ----------
24
- hist: numpy.ndarray
25
- The counts of the histograms.
26
- x_bin_edges: numpy.array
27
- The x bin edges of the histograms.
28
- y_bin_edges: numpy.array
29
- The y bin edges of the histograms.
30
- Use None for 1D histograms.
31
- x_label: str
32
- X bin edges label.
33
- y_label: str
34
- Y bin edges label.
35
- Use None for 1D histograms.
36
- meta_data: dict
37
- Dictionary with the histogram metadata.
38
- """
39
- validate_histogram(hist, y_bin_edges)
40
-
41
- meta_data["x_bin_edges"] = x_bin_edges
42
- meta_data["x_bin_edges_unit"] = (
43
- x_bin_edges.unit if isinstance(x_bin_edges, u.Quantity) else u.dimensionless_unscaled
44
- )
45
- if y_bin_edges is not None:
46
- meta_data["y_bin_edges"] = y_bin_edges
47
- meta_data["y_bin_edges_unit"] = (
48
- y_bin_edges.unit if isinstance(y_bin_edges, u.Quantity) else u.dimensionless_unscaled
49
- )
50
-
51
- if hist.ndim == 1:
52
- if x_label is not None:
53
- names = sanitize_name(x_label)
54
- try:
55
- names = meta_data["Title"]
56
- except KeyError:
57
- _logger.warning("Title not found in metadata.")
58
-
59
- table = Table(
60
- [
61
- x_bin_edges[:-1],
62
- hist,
63
- ],
64
- names=(names, sanitize_name("Values")),
65
- meta=meta_data,
66
- )
67
- else:
68
- if y_label is not None:
69
- names = [
70
- f"{sanitize_name(y_label).split('__')[0]}_{i}" for i in range(len(y_bin_edges[:-1]))
71
- ]
72
- try:
73
- names = [
74
- f"{(meta_data['Title']).split('__')[0]}_{sanitize_name(y_label)}_{i}"
75
- for i in range(len(y_bin_edges[:-1]))
76
- ]
77
- except KeyError:
78
- _logger.warning("Title not found in metadata.")
79
- names = [
80
- f"{sanitize_name(y_label).split('__')[0]}_{i}" for i in range(len(y_bin_edges[:-1]))
81
- ]
82
-
83
- table = Table(
84
- [hist[i, :] for i in range(len(y_bin_edges[:-1]))],
85
- names=names,
86
- meta=meta_data,
87
- )
88
-
89
- return table
90
-
91
-
92
- def validate_histogram(hist, y_bin_edges):
93
- """Validate histogram dimensions and y_bin_edges consistency.
94
-
95
- Parameters
96
- ----------
97
- hist (np.ndarray): The histogram array, expected to be 1D or 2D.
98
- y_bin_edges (array-like or None): Bin edges for the second dimension (if applicable).
99
-
100
- Raises
101
- ------
102
- ValueError: If histogram dimensions are invalid or inconsistent with y_bin_edges.
103
- """
104
- if hist.ndim not in (1, 2):
105
- raise ValueError("Histogram must be either 1D or 2D.")
106
-
107
- if hist.ndim == 1 and y_bin_edges is not None:
108
- raise ValueError("y_bin_edges should be None for 1D histograms.")
109
-
110
- if hist.ndim == 2 and y_bin_edges is None:
111
- raise ValueError("y_bin_edges should not be None for 2D histograms.")
112
-
113
-
114
- def read_hdf5(hdf5_file_name):
115
- """
116
- Read a hdf5 output file.
117
-
118
- Parameters
119
- ----------
120
- hdf5_file_name: str or Path
121
- Name or Path of the hdf5 file to read from.
122
-
123
- Returns
124
- -------
125
- list
126
- The list with the astropy.Table instances for the various 1D and 2D histograms saved
127
- in the hdf5 file.
128
- """
129
- if isinstance(hdf5_file_name, PosixPath):
130
- hdf5_file_name = hdf5_file_name.absolute().as_posix()
131
-
132
- tables_list = []
133
-
134
- with tables.open_file(hdf5_file_name, mode="r") as file:
135
- for node in file.walk_nodes("/", "Table"):
136
- table_path = node._v_pathname # pylint: disable=protected-access
137
- table = read_table(hdf5_file_name, table_path)
138
- tables_list.append(table)
139
- return tables_list
@@ -1,62 +0,0 @@
1
- #!/usr/bin/python3
2
- """Read file info and run headers from sim_telarray files."""
3
-
4
- from eventio import EventIOFile
5
- from eventio.simtel import MCRunHeader, MCShower, RunHeader
6
-
7
-
8
- def get_corsika_run_number(file):
9
- """
10
- Return the CORSIKA run number from a sim_telarray file.
11
-
12
- Parameters
13
- ----------
14
- file: str
15
- Path to the sim_telarray file.
16
-
17
- Returns
18
- -------
19
- int, None
20
- CORSIKA run number. Returns None if not found.
21
- """
22
- run_header = get_corsika_run_header(file)
23
- return run_header.get("run") if run_header else None
24
-
25
-
26
- def get_corsika_run_header(file):
27
- """
28
- Return the CORSIKA run header information from a sim_telarray file.
29
-
30
- Reads both RunHeader and MCRunHeader object from file and
31
- returns a merged dictionary. Adds primary id from the first event.
32
-
33
- Parameters
34
- ----------
35
- file: str
36
- Path to the sim_telarray file.
37
-
38
- Returns
39
- -------
40
- dict, None
41
- CORSIKA run header. Returns None if not found.
42
- """
43
- run_header = None
44
- mc_run_header = None
45
- primary_id = None
46
-
47
- with EventIOFile(file) as f:
48
- for o in f:
49
- if isinstance(o, RunHeader) and run_header is None:
50
- run_header = o.parse()
51
- elif isinstance(o, MCRunHeader) and mc_run_header is None:
52
- mc_run_header = o.parse()
53
- elif isinstance(o, MCShower): # get primary_id from first MCShower
54
- primary_id = o.parse().get("primary_id")
55
- if run_header and mc_run_header and primary_id is not None:
56
- break
57
-
58
- run_header = run_header or {}
59
- mc_run_header = mc_run_header or {}
60
- if primary_id is not None:
61
- mc_run_header["primary_id"] = primary_id
62
- return run_header | mc_run_header or None