gammasimtools 0.25.0__py3-none-any.whl → 0.27.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.25.0.dist-info → gammasimtools-0.27.0.dist-info}/METADATA +6 -1
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/RECORD +135 -130
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/entry_points.txt +3 -2
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/licenses/LICENSE +1 -1
- simtools/_version.py +2 -2
- simtools/application_control.py +35 -7
- simtools/applications/convert_geo_coordinates_of_array_elements.py +3 -3
- simtools/applications/db_add_file_to_db.py +1 -1
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +1 -1
- simtools/applications/db_add_value_from_json_to_db.py +1 -1
- simtools/applications/db_generate_compound_indexes.py +1 -1
- simtools/applications/db_get_array_layouts_from_db.py +3 -7
- simtools/applications/db_get_file_from_db.py +1 -1
- simtools/applications/db_get_parameter_from_db.py +1 -1
- simtools/applications/db_inspect_databases.py +1 -1
- simtools/applications/db_upload_model_repository.py +1 -1
- simtools/applications/derive_ctao_array_layouts.py +1 -2
- simtools/applications/{calculate_incident_angles.py → derive_incident_angle.py} +16 -18
- simtools/applications/derive_mirror_rnda.py +112 -180
- simtools/applications/derive_psf_parameters.py +0 -1
- simtools/applications/derive_pulse_shape_parameters.py +0 -1
- simtools/applications/derive_trigger_rates.py +1 -1
- simtools/applications/docs_produce_array_element_report.py +2 -8
- simtools/applications/docs_produce_calibration_reports.py +1 -3
- simtools/applications/docs_produce_model_parameter_reports.py +0 -2
- simtools/applications/docs_produce_simulation_configuration_report.py +1 -3
- simtools/applications/generate_array_config.py +0 -1
- simtools/applications/generate_corsika_histograms.py +79 -229
- simtools/applications/generate_regular_arrays.py +76 -69
- simtools/applications/generate_simtel_event_data.py +2 -2
- simtools/applications/maintain_simulation_model_add_production.py +2 -2
- simtools/applications/maintain_simulation_model_write_array_element_positions.py +87 -0
- simtools/applications/plot_array_layout.py +5 -111
- simtools/applications/plot_simulated_event_distributions.py +57 -0
- simtools/applications/plot_tabular_data.py +0 -1
- simtools/applications/plot_tabular_data_for_model_parameter.py +1 -6
- simtools/applications/production_derive_corsika_limits.py +1 -1
- simtools/applications/production_generate_grid.py +0 -1
- simtools/applications/run_application.py +1 -1
- simtools/applications/simulate_flasher.py +3 -15
- simtools/applications/simulate_illuminator.py +2 -11
- simtools/applications/simulate_pedestals.py +1 -5
- simtools/applications/simulate_prod.py +8 -11
- simtools/applications/simulate_prod_htcondor_generator.py +1 -1
- simtools/applications/submit_array_layouts.py +2 -4
- simtools/applications/submit_data_from_external.py +2 -1
- simtools/applications/submit_model_parameter_from_external.py +1 -3
- simtools/applications/validate_camera_efficiency.py +28 -28
- simtools/applications/validate_camera_fov.py +0 -1
- simtools/applications/validate_cumulative_psf.py +1 -5
- simtools/applications/validate_optics.py +2 -14
- simtools/atmosphere.py +83 -0
- simtools/camera/camera_efficiency.py +171 -53
- simtools/camera/single_photon_electron_spectrum.py +8 -7
- simtools/configuration/commandline_parser.py +82 -11
- simtools/configuration/configurator.py +6 -11
- simtools/constants.py +5 -0
- simtools/corsika/corsika_config.py +100 -202
- simtools/corsika/corsika_histograms.py +561 -1708
- simtools/corsika/primary_particle.py +1 -1
- simtools/data_model/metadata_collector.py +5 -2
- simtools/data_model/metadata_model.py +0 -4
- simtools/data_model/model_data_writer.py +59 -64
- simtools/data_model/schema.py +2 -0
- simtools/data_model/validate_data.py +1 -3
- simtools/db/db_handler.py +23 -10
- simtools/db/mongo_db.py +2 -2
- simtools/dependencies.py +81 -38
- simtools/io/ascii_handler.py +55 -5
- simtools/io/io_handler.py +23 -12
- simtools/io/table_handler.py +1 -1
- simtools/job_execution/job_manager.py +154 -79
- simtools/job_execution/process_pool.py +137 -0
- simtools/layout/array_layout.py +4 -13
- simtools/layout/array_layout_utils.py +348 -57
- simtools/model/array_model.py +23 -63
- simtools/model/calibration_model.py +4 -8
- simtools/model/legacy_model_parameter.py +134 -0
- simtools/model/model_parameter.py +147 -86
- simtools/model/model_utils.py +40 -6
- simtools/model/site_model.py +4 -8
- simtools/model/telescope_model.py +10 -16
- simtools/production_configuration/derive_corsika_limits.py +6 -11
- simtools/production_configuration/interpolation_handler.py +16 -16
- simtools/ray_tracing/incident_angles.py +92 -17
- simtools/ray_tracing/mirror_panel_psf.py +338 -222
- simtools/ray_tracing/psf_analysis.py +62 -48
- simtools/ray_tracing/psf_parameter_optimisation.py +3 -3
- simtools/ray_tracing/ray_tracing.py +43 -25
- simtools/reporting/docs_auto_report_generator.py +8 -13
- simtools/reporting/docs_read_parameters.py +2 -8
- simtools/runners/corsika_runner.py +52 -195
- simtools/runners/corsika_simtel_runner.py +77 -108
- simtools/runners/runner_services.py +214 -213
- simtools/runners/simtel_runner.py +27 -160
- simtools/runners/simtools_runner.py +11 -73
- simtools/schemas/application_workflow.metaschema.yml +8 -0
- simtools/settings.py +173 -0
- simtools/{io/eventio_handler.py → sim_events/file_info.py} +3 -3
- simtools/{simtel/simtel_io_event_histograms.py → sim_events/histograms.py} +25 -15
- simtools/{simtel/simtel_io_event_reader.py → sim_events/reader.py} +20 -17
- simtools/{simtel/simtel_io_event_writer.py → sim_events/writer.py} +84 -25
- simtools/simtel/pulse_shapes.py +7 -2
- simtools/simtel/simtel_config_writer.py +79 -91
- simtools/simtel/simtel_seeds.py +184 -0
- simtools/simtel/simtel_table_reader.py +6 -4
- simtools/simtel/simulator_array.py +114 -109
- simtools/simtel/simulator_camera_efficiency.py +68 -46
- simtools/simtel/simulator_light_emission.py +164 -132
- simtools/simtel/simulator_ray_tracing.py +80 -71
- simtools/simulator.py +137 -355
- simtools/telescope_trigger_rates.py +3 -4
- simtools/testing/assertions.py +84 -33
- simtools/testing/configuration.py +1 -2
- simtools/testing/helpers.py +2 -3
- simtools/testing/log_inspector.py +1 -0
- simtools/testing/sim_telarray_metadata.py +14 -12
- simtools/testing/validate_output.py +121 -42
- simtools/utils/general.py +43 -17
- simtools/utils/geometry.py +0 -77
- simtools/utils/names.py +5 -5
- simtools/utils/random.py +36 -0
- simtools/visualization/legend_handlers.py +7 -6
- simtools/visualization/plot_array_layout.py +91 -16
- simtools/visualization/plot_corsika_histograms.py +145 -605
- simtools/visualization/plot_incident_angles.py +48 -1
- simtools/visualization/plot_mirrors.py +1 -4
- simtools/visualization/plot_pixels.py +2 -4
- simtools/visualization/plot_psf.py +160 -19
- simtools/visualization/plot_simtel_event_histograms.py +4 -4
- simtools/visualization/plot_simtel_events.py +6 -11
- simtools/visualization/plot_tables.py +8 -19
- simtools/visualization/visualize.py +22 -2
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +0 -160
- simtools/applications/print_version.py +0 -53
- simtools/io/hdf5_handler.py +0 -139
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/top_level.txt +0 -0
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
+
import astropy.units as u
|
|
7
|
+
from astropy.table import QTable, Table
|
|
8
|
+
|
|
6
9
|
import simtools.utils.general as gen
|
|
7
10
|
from simtools.data_model import data_reader
|
|
8
11
|
from simtools.data_model.metadata_collector import MetadataCollector
|
|
@@ -137,7 +140,7 @@ def merge_array_layouts(layouts_1, layouts_2):
|
|
|
137
140
|
return merged_layout
|
|
138
141
|
|
|
139
142
|
|
|
140
|
-
def write_array_layouts(array_layouts, args_dict
|
|
143
|
+
def write_array_layouts(array_layouts, args_dict):
|
|
141
144
|
"""
|
|
142
145
|
Write array layouts as model parameter.
|
|
143
146
|
|
|
@@ -147,8 +150,6 @@ def write_array_layouts(array_layouts, args_dict, db_config):
|
|
|
147
150
|
Command line arguments.
|
|
148
151
|
array_layouts : dict
|
|
149
152
|
Array layouts to be written.
|
|
150
|
-
db_config : dict
|
|
151
|
-
Database configuration.
|
|
152
153
|
"""
|
|
153
154
|
site = args_dict.get("site") or array_layouts.get("site")
|
|
154
155
|
_logger.info(f"Writing updated array layouts to the database for site {site}.")
|
|
@@ -165,7 +166,6 @@ def write_array_layouts(array_layouts, args_dict, db_config):
|
|
|
165
166
|
instrument=f"OBS-{site}",
|
|
166
167
|
parameter_version=args_dict.get("updated_parameter_version"),
|
|
167
168
|
output_file=output_file,
|
|
168
|
-
db_config=db_config,
|
|
169
169
|
)
|
|
170
170
|
MetadataCollector.dump(
|
|
171
171
|
args_dict,
|
|
@@ -208,9 +208,7 @@ def validate_array_layouts_with_db(production_table, array_layouts):
|
|
|
208
208
|
return array_layouts
|
|
209
209
|
|
|
210
210
|
|
|
211
|
-
def get_array_layouts_from_parameter_file(
|
|
212
|
-
file_path, model_version, db_config, coordinate_system="ground"
|
|
213
|
-
):
|
|
211
|
+
def get_array_layouts_from_parameter_file(file_path, model_version, coordinate_system="ground"):
|
|
214
212
|
"""
|
|
215
213
|
Retrieve array layouts from parameter file.
|
|
216
214
|
|
|
@@ -220,8 +218,6 @@ def get_array_layouts_from_parameter_file(
|
|
|
220
218
|
Path to the array layout parameter file.
|
|
221
219
|
model_version : str
|
|
222
220
|
Model version to retrieve.
|
|
223
|
-
db_config : dict
|
|
224
|
-
Database configuration.
|
|
225
221
|
coordinate_system : str
|
|
226
222
|
Coordinate system to use for the array elements (default is "ground").
|
|
227
223
|
|
|
@@ -237,24 +233,19 @@ def get_array_layouts_from_parameter_file(
|
|
|
237
233
|
raise ValueError("Missing 'value' key in layout file.") from exc
|
|
238
234
|
site = array_layouts.get("site")
|
|
239
235
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
layout.get("elements"),
|
|
248
|
-
layout["name"],
|
|
249
|
-
coordinate_system,
|
|
250
|
-
)
|
|
236
|
+
return [
|
|
237
|
+
_get_array_layout_dict(
|
|
238
|
+
model_version,
|
|
239
|
+
site,
|
|
240
|
+
layout.get("elements"),
|
|
241
|
+
layout["name"],
|
|
242
|
+
coordinate_system,
|
|
251
243
|
)
|
|
252
|
-
|
|
244
|
+
for layout in value
|
|
245
|
+
]
|
|
253
246
|
|
|
254
247
|
|
|
255
|
-
def get_array_layouts_from_db(
|
|
256
|
-
layout_name, site, model_version, db_config, coordinate_system="ground"
|
|
257
|
-
):
|
|
248
|
+
def get_array_layouts_from_db(layout_name, site, model_version, coordinate_system="ground"):
|
|
258
249
|
"""
|
|
259
250
|
Retrieve all array layouts from the database and return as list of astropy tables.
|
|
260
251
|
|
|
@@ -266,8 +257,6 @@ def get_array_layouts_from_db(
|
|
|
266
257
|
Site identifier.
|
|
267
258
|
model_version : str
|
|
268
259
|
Model version to retrieve.
|
|
269
|
-
db_config : dict
|
|
270
|
-
Database configuration.
|
|
271
260
|
coordinate_system : str
|
|
272
261
|
Coordinate system to use for the array elements (default is "ground").
|
|
273
262
|
|
|
@@ -280,23 +269,20 @@ def get_array_layouts_from_db(
|
|
|
280
269
|
if layout_name:
|
|
281
270
|
layout_names = gen.ensure_iterable(layout_name)
|
|
282
271
|
else:
|
|
283
|
-
site_model = SiteModel(site=site, model_version=model_version
|
|
272
|
+
site_model = SiteModel(site=site, model_version=model_version)
|
|
284
273
|
layout_names = site_model.get_list_of_array_layouts()
|
|
285
274
|
|
|
286
|
-
layouts = [
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
db_config, model_version, site, None, _layout_name, coordinate_system
|
|
291
|
-
)
|
|
292
|
-
)
|
|
275
|
+
layouts = [
|
|
276
|
+
_get_array_layout_dict(model_version, site, None, _layout_name, coordinate_system)
|
|
277
|
+
for _layout_name in layout_names
|
|
278
|
+
]
|
|
293
279
|
if len(layouts) == 1:
|
|
294
280
|
return layouts[0]
|
|
295
281
|
return layouts
|
|
296
282
|
|
|
297
283
|
|
|
298
284
|
def get_array_layouts_using_telescope_lists_from_db(
|
|
299
|
-
telescope_lists, site, model_version,
|
|
285
|
+
telescope_lists, site, model_version, coordinate_system="ground"
|
|
300
286
|
):
|
|
301
287
|
"""
|
|
302
288
|
Retrieve array layouts from the database using telescope lists.
|
|
@@ -309,8 +295,6 @@ def get_array_layouts_using_telescope_lists_from_db(
|
|
|
309
295
|
Site identifier.
|
|
310
296
|
model_version : str
|
|
311
297
|
Model version to retrieve.
|
|
312
|
-
db_config : dict
|
|
313
|
-
Database configuration.
|
|
314
298
|
coordinate_system : str
|
|
315
299
|
Coordinate system to use for the array elements (default is "ground").
|
|
316
300
|
|
|
@@ -333,9 +317,7 @@ def get_array_layouts_using_telescope_lists_from_db(
|
|
|
333
317
|
_site = sites.pop()
|
|
334
318
|
|
|
335
319
|
layouts.append(
|
|
336
|
-
_get_array_layout_dict(
|
|
337
|
-
db_config, model_version, _site, telescope_list, None, coordinate_system
|
|
338
|
-
)
|
|
320
|
+
_get_array_layout_dict(model_version, _site, telescope_list, None, coordinate_system)
|
|
339
321
|
)
|
|
340
322
|
return layouts
|
|
341
323
|
|
|
@@ -357,23 +339,18 @@ def get_array_layouts_from_file(file_path):
|
|
|
357
339
|
if isinstance(file_path, str | Path):
|
|
358
340
|
file_path = [file_path]
|
|
359
341
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
)
|
|
368
|
-
return layouts
|
|
342
|
+
return [
|
|
343
|
+
{
|
|
344
|
+
"name": Path(_file).stem,
|
|
345
|
+
"array_elements": data_reader.read_table_from_file(file_name=_file),
|
|
346
|
+
}
|
|
347
|
+
for _file in file_path
|
|
348
|
+
]
|
|
369
349
|
|
|
370
350
|
|
|
371
|
-
def _get_array_layout_dict(
|
|
372
|
-
db_config, model_version, site, telescope_list, layout_name, coordinate_system
|
|
373
|
-
):
|
|
351
|
+
def _get_array_layout_dict(model_version, site, telescope_list, layout_name, coordinate_system):
|
|
374
352
|
"""Return array layout dictionary for a given telescope list."""
|
|
375
353
|
array_model = ArrayModel(
|
|
376
|
-
db_config=db_config,
|
|
377
354
|
model_version=model_version,
|
|
378
355
|
site=site,
|
|
379
356
|
array_elements=telescope_list,
|
|
@@ -388,7 +365,7 @@ def _get_array_layout_dict(
|
|
|
388
365
|
}
|
|
389
366
|
|
|
390
367
|
|
|
391
|
-
def get_array_elements_from_db_for_layouts(layouts, site, model_version
|
|
368
|
+
def get_array_elements_from_db_for_layouts(layouts, site, model_version):
|
|
392
369
|
"""
|
|
393
370
|
Get list of array elements from the database for given list of layout names.
|
|
394
371
|
|
|
@@ -408,17 +385,331 @@ def get_array_elements_from_db_for_layouts(layouts, site, model_version, db_conf
|
|
|
408
385
|
Site name for the array layouts.
|
|
409
386
|
model_version : str
|
|
410
387
|
Model version for the array layouts.
|
|
411
|
-
db_config : dict
|
|
412
|
-
Database configuration dictionary.
|
|
413
388
|
|
|
414
389
|
Returns
|
|
415
390
|
-------
|
|
416
391
|
dict
|
|
417
392
|
Dictionary mapping layout names to telescope IDs.
|
|
418
393
|
"""
|
|
419
|
-
site_model = SiteModel(site=site, model_version=model_version
|
|
394
|
+
site_model = SiteModel(site=site, model_version=model_version)
|
|
420
395
|
layout_names = site_model.get_list_of_array_layouts() if layouts == ["all"] else layouts
|
|
421
396
|
layout_dict = {}
|
|
422
397
|
for layout_name in layout_names:
|
|
423
398
|
layout_dict[layout_name] = site_model.get_array_elements_for_layout(layout_name)
|
|
424
399
|
return layout_dict
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def read_layouts(args_dict):
|
|
403
|
+
"""
|
|
404
|
+
Read array layouts from the database or parameter file.
|
|
405
|
+
|
|
406
|
+
Parameters
|
|
407
|
+
----------
|
|
408
|
+
args_dict : dict
|
|
409
|
+
Dictionary with command line arguments.
|
|
410
|
+
|
|
411
|
+
Returns
|
|
412
|
+
-------
|
|
413
|
+
tuple
|
|
414
|
+
A tuple containing:
|
|
415
|
+
- list: List of array layouts.
|
|
416
|
+
- list or None: Background layout or None if not provided.
|
|
417
|
+
"""
|
|
418
|
+
background_layout = None
|
|
419
|
+
if args_dict.get("array_layout_name_background"):
|
|
420
|
+
background_layout = get_array_layouts_from_db(
|
|
421
|
+
args_dict["array_layout_name_background"],
|
|
422
|
+
args_dict["site"],
|
|
423
|
+
args_dict["model_version"],
|
|
424
|
+
args_dict["coordinate_system"],
|
|
425
|
+
)["array_elements"]
|
|
426
|
+
|
|
427
|
+
if args_dict["array_layout_name"] is not None or args_dict["plot_all_layouts"]:
|
|
428
|
+
_logger.info("Plotting array from DB using layout array name(s).")
|
|
429
|
+
layouts = get_array_layouts_from_db(
|
|
430
|
+
args_dict["array_layout_name"],
|
|
431
|
+
args_dict["site"],
|
|
432
|
+
args_dict["model_version"],
|
|
433
|
+
args_dict["coordinate_system"],
|
|
434
|
+
)
|
|
435
|
+
if isinstance(layouts, list):
|
|
436
|
+
return layouts, background_layout
|
|
437
|
+
return [layouts], background_layout
|
|
438
|
+
|
|
439
|
+
if args_dict["array_layout_parameter_file"] is not None:
|
|
440
|
+
_logger.info("Plotting array from parameter file(s).")
|
|
441
|
+
return get_array_layouts_from_parameter_file(
|
|
442
|
+
args_dict["array_layout_parameter_file"],
|
|
443
|
+
args_dict["model_version"],
|
|
444
|
+
args_dict["coordinate_system"],
|
|
445
|
+
), background_layout
|
|
446
|
+
|
|
447
|
+
if args_dict["array_layout_file"] is not None:
|
|
448
|
+
_logger.info("Plotting array from telescope table file(s).")
|
|
449
|
+
return get_array_layouts_from_file(args_dict["array_layout_file"]), background_layout
|
|
450
|
+
if args_dict["array_element_list"] is not None:
|
|
451
|
+
_logger.info("Plotting array from list of array elements.")
|
|
452
|
+
return get_array_layouts_using_telescope_lists_from_db(
|
|
453
|
+
[args_dict["array_element_list"]],
|
|
454
|
+
args_dict["site"],
|
|
455
|
+
args_dict["model_version"],
|
|
456
|
+
args_dict["coordinate_system"],
|
|
457
|
+
), background_layout
|
|
458
|
+
|
|
459
|
+
return [], background_layout
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
def _get_array_name(array_name):
|
|
463
|
+
"""
|
|
464
|
+
Return telescope size and number of telescopes from regular array name.
|
|
465
|
+
|
|
466
|
+
Finetuned to array names like "4MST", "1LST", etc.
|
|
467
|
+
|
|
468
|
+
Parameters
|
|
469
|
+
----------
|
|
470
|
+
array_name : str
|
|
471
|
+
Name of the regular array (e.g. "4MST").
|
|
472
|
+
|
|
473
|
+
Returns
|
|
474
|
+
-------
|
|
475
|
+
tel_size : str
|
|
476
|
+
Telescope size (e.g. "MST").
|
|
477
|
+
n_tel : int
|
|
478
|
+
Number of telescopes (e.g. 4).
|
|
479
|
+
"""
|
|
480
|
+
if len(array_name) < 2 or not array_name[0].isdigit():
|
|
481
|
+
raise ValueError(f"Invalid array_name: '{array_name}'")
|
|
482
|
+
|
|
483
|
+
return array_name[1:], int(array_name[0])
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
def _create_star_array(tel_name, pos_x, pos_y, pos_z, n_telescopes, tel_type, site, distance):
|
|
487
|
+
"""Create star-shaped array positions along x and y axes."""
|
|
488
|
+
axis_sequence = ["x", "y", "-x", "-y"]
|
|
489
|
+
step = 1
|
|
490
|
+
for i in range(n_telescopes):
|
|
491
|
+
tel_name.append(
|
|
492
|
+
names.generate_array_element_name_from_type_site_id(tel_type, site, f"{i + 1:02d}")
|
|
493
|
+
)
|
|
494
|
+
axis = axis_sequence[i % 4]
|
|
495
|
+
dist = distance * step
|
|
496
|
+
if axis == "x":
|
|
497
|
+
pos_x.append(dist)
|
|
498
|
+
pos_y.append(0 * u.m)
|
|
499
|
+
elif axis == "-x":
|
|
500
|
+
pos_x.append(-dist)
|
|
501
|
+
pos_y.append(0 * u.m)
|
|
502
|
+
elif axis == "y":
|
|
503
|
+
pos_x.append(0 * u.m)
|
|
504
|
+
pos_y.append(dist)
|
|
505
|
+
elif axis == "-y":
|
|
506
|
+
pos_x.append(0 * u.m)
|
|
507
|
+
pos_y.append(-dist)
|
|
508
|
+
pos_z.append(0 * u.m)
|
|
509
|
+
|
|
510
|
+
if (i + 1) % 4 == 0:
|
|
511
|
+
step += 1
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
def _create_square_array(tel_name, pos_x, pos_y, pos_z, n_tel, tel_type, site, distance):
|
|
515
|
+
"""Create square array positions."""
|
|
516
|
+
if n_tel == 1:
|
|
517
|
+
tel_name.append(names.generate_array_element_name_from_type_site_id(tel_type, site, "01"))
|
|
518
|
+
pos_x.append(0 * u.m)
|
|
519
|
+
pos_y.append(0 * u.m)
|
|
520
|
+
pos_z.append(0 * u.m)
|
|
521
|
+
elif n_tel == 4:
|
|
522
|
+
for i in range(1, 5):
|
|
523
|
+
tel_name.append(
|
|
524
|
+
names.generate_array_element_name_from_type_site_id(tel_type, site, f"0{i}")
|
|
525
|
+
)
|
|
526
|
+
pos_x.append(distance * (-1) ** (i // 2))
|
|
527
|
+
pos_y.append(distance * (-1) ** (i % 2))
|
|
528
|
+
pos_z.append(0 * u.m)
|
|
529
|
+
else:
|
|
530
|
+
raise ValueError(f"Unsupported number of telescopes for square array: {n_tel}.")
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
def create_regular_array(
|
|
534
|
+
array_name, site, n_telescopes, telescope_type, telescope_distance, shape="square"
|
|
535
|
+
):
|
|
536
|
+
"""
|
|
537
|
+
Create a regular array layout table.
|
|
538
|
+
|
|
539
|
+
Parameters
|
|
540
|
+
----------
|
|
541
|
+
array_name : str
|
|
542
|
+
Name of the regular array (e.g. "4MST").
|
|
543
|
+
site : str
|
|
544
|
+
Site identifier.
|
|
545
|
+
n_telescopes : int
|
|
546
|
+
Number of telescopes in the array.
|
|
547
|
+
telescope_type : str
|
|
548
|
+
Type of telescope (e.g. "MST").
|
|
549
|
+
telescope_distance : Quantity
|
|
550
|
+
Distance between telescopes in the array.
|
|
551
|
+
shape : str
|
|
552
|
+
Shape of the array: "square" or "star" (default: "square").
|
|
553
|
+
|
|
554
|
+
Returns
|
|
555
|
+
-------
|
|
556
|
+
astropy.table.Table
|
|
557
|
+
Table with the regular array layout.
|
|
558
|
+
"""
|
|
559
|
+
tel_name, pos_x, pos_y, pos_z = [], [], [], []
|
|
560
|
+
|
|
561
|
+
if shape == "square":
|
|
562
|
+
_create_square_array(
|
|
563
|
+
tel_name,
|
|
564
|
+
pos_x,
|
|
565
|
+
pos_y,
|
|
566
|
+
pos_z,
|
|
567
|
+
n_telescopes,
|
|
568
|
+
telescope_type,
|
|
569
|
+
site,
|
|
570
|
+
telescope_distance,
|
|
571
|
+
)
|
|
572
|
+
elif shape == "star":
|
|
573
|
+
_create_star_array(
|
|
574
|
+
tel_name,
|
|
575
|
+
pos_x,
|
|
576
|
+
pos_y,
|
|
577
|
+
pos_z,
|
|
578
|
+
n_telescopes,
|
|
579
|
+
telescope_type,
|
|
580
|
+
site,
|
|
581
|
+
telescope_distance,
|
|
582
|
+
)
|
|
583
|
+
else:
|
|
584
|
+
raise ValueError(f"Unsupported array shape: {shape}. Allowed: 'square' or 'star'.")
|
|
585
|
+
|
|
586
|
+
table = QTable(meta={"array_name": array_name, "site": site})
|
|
587
|
+
table["telescope_name"] = tel_name
|
|
588
|
+
table["position_x"] = pos_x
|
|
589
|
+
table["position_y"] = pos_y
|
|
590
|
+
table["position_z"] = pos_z
|
|
591
|
+
table.sort("telescope_name")
|
|
592
|
+
_logger.info(f"Regular array layout table:\n{table}")
|
|
593
|
+
|
|
594
|
+
return table
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
def write_array_elements_from_file_to_repository(
|
|
598
|
+
coordinate_system, input_file, repository_path, parameter_version
|
|
599
|
+
):
|
|
600
|
+
"""
|
|
601
|
+
Read array elements from file and write their positions to model repository.
|
|
602
|
+
|
|
603
|
+
Writes one model parameter file per array elements.
|
|
604
|
+
|
|
605
|
+
Parameters
|
|
606
|
+
----------
|
|
607
|
+
coordinate_system : str
|
|
608
|
+
Coordinate system of array element positions (utm or ground).
|
|
609
|
+
input_file : str or Path
|
|
610
|
+
Path to input file with array element positions.
|
|
611
|
+
repository_path : str or Path
|
|
612
|
+
Path to model repository.
|
|
613
|
+
parameter_version : str
|
|
614
|
+
Parameter version to use when writing to repository.
|
|
615
|
+
"""
|
|
616
|
+
repository_path = Path(repository_path)
|
|
617
|
+
|
|
618
|
+
array_elements = Table.read(input_file)
|
|
619
|
+
|
|
620
|
+
if coordinate_system == "ground":
|
|
621
|
+
parameter_name = "array_element_position_ground"
|
|
622
|
+
x = array_elements["position_x"].quantity.to(u.m).value
|
|
623
|
+
y = array_elements["position_y"].quantity.to(u.m).value
|
|
624
|
+
alt = array_elements["position_z"].quantity.to(u.m).value
|
|
625
|
+
elif coordinate_system == "utm":
|
|
626
|
+
x = array_elements["utm_east"].quantity.to(u.m).value
|
|
627
|
+
y = array_elements["utm_north"].quantity.to(u.m).value
|
|
628
|
+
alt = array_elements["altitude"].quantity.to(u.m).value
|
|
629
|
+
parameter_name = "array_element_position_utm"
|
|
630
|
+
else:
|
|
631
|
+
raise ValueError(
|
|
632
|
+
f"Unsupported coordinate system: {coordinate_system}. Allowed are 'utm' and 'ground'."
|
|
633
|
+
)
|
|
634
|
+
|
|
635
|
+
for i, row in enumerate(array_elements):
|
|
636
|
+
instrument = (
|
|
637
|
+
row["telescope_name"]
|
|
638
|
+
if "telescope_name" in array_elements.colnames
|
|
639
|
+
else f"{row['asset_code']}-{row['sequence_number']}"
|
|
640
|
+
)
|
|
641
|
+
output_path = repository_path / f"{instrument}"
|
|
642
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
|
643
|
+
_logger.info(f"Writing array element positions ({coordinate_system}) to {output_path}")
|
|
644
|
+
|
|
645
|
+
ModelDataWriter.dump_model_parameter(
|
|
646
|
+
parameter_name=parameter_name,
|
|
647
|
+
instrument=instrument,
|
|
648
|
+
value=f"{x[i]} {y[i]} {alt[i]}",
|
|
649
|
+
unit="m",
|
|
650
|
+
parameter_version=parameter_version,
|
|
651
|
+
output_path=repository_path / instrument,
|
|
652
|
+
output_file=f"{parameter_name}.json",
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
def write_array_elements_info_yaml(
|
|
657
|
+
array_table, site, model_version, output_file, parameter_version="2.0.0"
|
|
658
|
+
):
|
|
659
|
+
"""
|
|
660
|
+
Write YAML file for array layout in a format compatible with overwrite.
|
|
661
|
+
|
|
662
|
+
Parameters
|
|
663
|
+
----------
|
|
664
|
+
array_table : astropy.table.Table
|
|
665
|
+
Table with telescope positions.
|
|
666
|
+
site : str
|
|
667
|
+
Site identifier (e.g., 'North' or 'South').
|
|
668
|
+
model_version : str
|
|
669
|
+
Model version.
|
|
670
|
+
output_file : Path
|
|
671
|
+
Path to the output YAML file.
|
|
672
|
+
parameter_version : str
|
|
673
|
+
Parameter version to use in the YAML file.
|
|
674
|
+
"""
|
|
675
|
+
telescope_names = [str(name) for name in array_table["telescope_name"]]
|
|
676
|
+
|
|
677
|
+
data = {
|
|
678
|
+
"model_version": model_version,
|
|
679
|
+
"model_update": "patch_update",
|
|
680
|
+
"model_version_history": [model_version],
|
|
681
|
+
"description": f"Regular array layout: {array_table.meta['array_name']}",
|
|
682
|
+
"changes": {
|
|
683
|
+
f"OBS-{site}": {
|
|
684
|
+
"array_layouts": {
|
|
685
|
+
"version": parameter_version,
|
|
686
|
+
"value": [],
|
|
687
|
+
"unit": None,
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
},
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
data["changes"][f"OBS-{site}"]["array_layouts"]["value"].append(
|
|
694
|
+
{"name": array_table.meta["array_name"], "elements": telescope_names}
|
|
695
|
+
)
|
|
696
|
+
|
|
697
|
+
for tel_name, pos_x, pos_y, pos_z in zip(
|
|
698
|
+
telescope_names,
|
|
699
|
+
array_table["position_x"],
|
|
700
|
+
array_table["position_y"],
|
|
701
|
+
array_table["position_z"],
|
|
702
|
+
):
|
|
703
|
+
data["changes"][tel_name] = {
|
|
704
|
+
"array_element_position_ground": {
|
|
705
|
+
"version": parameter_version,
|
|
706
|
+
"value": [
|
|
707
|
+
float(pos_x.to(u.m).value),
|
|
708
|
+
float(pos_y.to(u.m).value),
|
|
709
|
+
float(pos_z.to(u.m).value),
|
|
710
|
+
],
|
|
711
|
+
"unit": "m",
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
ascii_handler.write_data_to_file(data, output_file)
|