gammasimtools 0.6.1__py3-none-any.whl → 0.8.2__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.8.2.dist-info/METADATA +173 -0
- gammasimtools-0.8.2.dist-info/RECORD +345 -0
- {gammasimtools-0.6.1.dist-info → gammasimtools-0.8.2.dist-info}/WHEEL +1 -1
- gammasimtools-0.8.2.dist-info/entry_points.txt +31 -0
- simtools/_dev_version/__init__.py +9 -0
- simtools/_version.py +2 -2
- simtools/applications/calculate_trigger_rate.py +210 -0
- simtools/applications/convert_all_model_parameters_from_simtel.py +372 -0
- simtools/applications/{print_array_elements.py → convert_geo_coordinates_of_array_elements.py} +58 -63
- simtools/applications/convert_model_parameter_from_simtel.py +119 -0
- simtools/applications/{add_file_to_db.py → db_add_file_to_db.py} +70 -60
- simtools/applications/db_add_model_parameters_from_repository_to_db.py +184 -0
- simtools/applications/db_add_value_from_json_to_db.py +105 -0
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +180 -0
- simtools/applications/db_get_array_layouts_from_db.py +162 -0
- simtools/applications/{get_file_from_db.py → db_get_file_from_db.py} +30 -34
- simtools/applications/db_get_parameter_from_db.py +131 -0
- simtools/applications/db_inspect_databases.py +52 -0
- simtools/applications/derive_mirror_rnda.py +39 -255
- simtools/applications/derive_psf_parameters.py +441 -0
- simtools/applications/generate_array_config.py +82 -0
- simtools/applications/generate_corsika_histograms.py +52 -52
- simtools/applications/generate_default_metadata.py +5 -8
- simtools/applications/generate_regular_arrays.py +117 -0
- simtools/applications/generate_simtel_array_histograms.py +97 -56
- simtools/applications/plot_array_layout.py +345 -115
- simtools/applications/production_generate_simulation_config.py +158 -0
- simtools/applications/production_scale_events.py +168 -0
- simtools/applications/simulate_light_emission.py +478 -0
- simtools/applications/simulate_prod.py +97 -175
- simtools/applications/submit_data_from_external.py +9 -12
- simtools/applications/submit_model_parameter_from_external.py +122 -0
- simtools/applications/validate_camera_efficiency.py +35 -102
- simtools/applications/validate_camera_fov.py +20 -19
- simtools/applications/{compare_cumulative_psf.py → validate_cumulative_psf.py} +45 -44
- simtools/applications/validate_file_using_schema.py +111 -47
- simtools/applications/validate_optics.py +17 -22
- simtools/camera_efficiency.py +193 -202
- simtools/configuration/commandline_parser.py +384 -96
- simtools/configuration/configurator.py +55 -71
- simtools/constants.py +5 -5
- simtools/corsika/corsika_config.py +482 -342
- simtools/corsika/corsika_histograms.py +226 -204
- simtools/corsika/corsika_histograms_visualize.py +23 -24
- simtools/corsika/primary_particle.py +159 -0
- simtools/data_model/data_reader.py +25 -20
- simtools/data_model/format_checkers.py +52 -0
- simtools/data_model/metadata_collector.py +211 -185
- simtools/data_model/metadata_model.py +115 -37
- simtools/data_model/model_data_writer.py +335 -26
- simtools/data_model/validate_data.py +366 -154
- simtools/db/db_array_elements.py +130 -0
- simtools/db/db_from_repo_handler.py +106 -0
- simtools/db/db_handler.py +1246 -0
- simtools/io_operations/hdf5_handler.py +3 -1
- simtools/io_operations/io_handler.py +32 -57
- simtools/job_execution/job_manager.py +82 -69
- simtools/layout/array_layout.py +325 -537
- simtools/layout/geo_coordinates.py +8 -11
- simtools/layout/telescope_position.py +163 -86
- simtools/model/array_model.py +312 -259
- simtools/model/calibration_model.py +50 -0
- simtools/model/camera.py +277 -523
- simtools/model/mirrors.py +68 -49
- simtools/model/model_parameter.py +602 -0
- simtools/model/model_utils.py +11 -39
- simtools/model/site_model.py +161 -0
- simtools/model/telescope_model.py +143 -633
- simtools/production_configuration/calculate_statistical_errors_grid_point.py +454 -0
- simtools/production_configuration/event_scaler.py +146 -0
- simtools/production_configuration/generate_simulation_config.py +193 -0
- simtools/production_configuration/interpolation_handler.py +197 -0
- simtools/ray_tracing/__init__.py +0 -0
- simtools/ray_tracing/mirror_panel_psf.py +280 -0
- simtools/{psf_analysis.py → ray_tracing/psf_analysis.py} +133 -47
- simtools/ray_tracing/ray_tracing.py +646 -0
- simtools/runners/__init__.py +0 -0
- simtools/runners/corsika_runner.py +240 -0
- simtools/runners/corsika_simtel_runner.py +225 -0
- simtools/runners/runner_services.py +307 -0
- simtools/runners/simtel_runner.py +224 -0
- simtools/schemas/array_elements.yml +137 -0
- simtools/schemas/integration_tests_config.metaschema.yml +93 -0
- simtools/schemas/metadata.metaschema.yml +6 -0
- simtools/schemas/model_parameter.metaschema.yml +78 -0
- simtools/schemas/{data.metaschema.yml → model_parameter_and_data_schema.metaschema.yml} +27 -44
- simtools/schemas/model_parameters/adjust_gain.schema.yml +37 -0
- simtools/schemas/model_parameters/altitude.schema.yml +37 -0
- simtools/schemas/model_parameters/array_coordinates.schema.yml +33 -0
- simtools/schemas/model_parameters/array_coordinates_UTM.schema.yml +77 -0
- simtools/schemas/model_parameters/array_element_position_ground.schema.yml +39 -0
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +39 -0
- simtools/schemas/model_parameters/array_layouts.schema.yml +48 -0
- simtools/schemas/model_parameters/array_triggers.schema.yml +93 -0
- simtools/schemas/model_parameters/asum_clipping.schema.yml +38 -0
- simtools/schemas/model_parameters/asum_offset.schema.yml +35 -0
- simtools/schemas/model_parameters/asum_shaping.schema.yml +35 -0
- simtools/schemas/model_parameters/asum_threshold.schema.yml +38 -0
- simtools/schemas/model_parameters/atmospheric_profile.schema.yml +32 -0
- simtools/schemas/model_parameters/atmospheric_transmission.schema.yml +35 -0
- simtools/schemas/model_parameters/axes_offsets.schema.yml +53 -0
- simtools/schemas/model_parameters/camera_body_diameter.schema.yml +40 -0
- simtools/schemas/model_parameters/camera_body_shape.schema.yml +45 -0
- simtools/schemas/model_parameters/camera_config_file.schema.yml +40 -0
- simtools/schemas/model_parameters/camera_config_rotate.schema.yml +36 -0
- simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +43 -0
- simtools/schemas/model_parameters/camera_degraded_map.schema.yml +42 -0
- simtools/schemas/model_parameters/camera_depth.schema.yml +42 -0
- simtools/schemas/model_parameters/camera_filter.schema.yml +45 -0
- simtools/schemas/model_parameters/camera_filter_incidence_angle.schema.yml +29 -0
- simtools/schemas/model_parameters/camera_pixels.schema.yml +36 -0
- simtools/schemas/model_parameters/camera_transmission.schema.yml +41 -0
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +36 -0
- simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +35 -0
- simtools/schemas/model_parameters/corsika_cherenkov_photon_bunch_size.schema.yml +27 -0
- simtools/schemas/model_parameters/corsika_cherenkov_photon_wavelength_range.schema.yml +38 -0
- simtools/schemas/model_parameters/corsika_first_interaction_height.schema.yml +28 -0
- simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +23 -0
- simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +27 -0
- simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +28 -0
- simtools/schemas/model_parameters/corsika_longitudinal_shower_development.schema.yml +27 -0
- simtools/schemas/model_parameters/corsika_observation_level.schema.yml +38 -0
- simtools/schemas/model_parameters/corsika_particle_kinetic_energy_cutoff.schema.yml +52 -0
- simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +27 -0
- simtools/schemas/model_parameters/dark_events.schema.yml +32 -0
- simtools/schemas/model_parameters/default_trigger.schema.yml +35 -0
- simtools/schemas/model_parameters/design_model.schema.yml +31 -0
- simtools/schemas/model_parameters/disc_ac_coupled.schema.yml +32 -0
- simtools/schemas/model_parameters/disc_bins.schema.yml +39 -0
- simtools/schemas/model_parameters/disc_start.schema.yml +41 -0
- simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +42 -0
- simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +41 -0
- simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +41 -0
- simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +39 -0
- simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +40 -0
- simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +41 -0
- simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +33 -0
- simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +42 -0
- simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +37 -0
- simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +44 -0
- simtools/schemas/model_parameters/discriminator_threshold.schema.yml +36 -0
- simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +45 -0
- simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +40 -0
- simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +41 -0
- simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +38 -0
- simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +38 -0
- simtools/schemas/model_parameters/dish_shape_length.schema.yml +41 -0
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +38 -0
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +38 -0
- simtools/schemas/model_parameters/dsum_offset.schema.yml +37 -0
- simtools/schemas/model_parameters/dsum_pedsub.schema.yml +33 -0
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +39 -0
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +44 -0
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +38 -0
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +45 -0
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +44 -0
- simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +32 -0
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +43 -0
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +42 -0
- simtools/schemas/model_parameters/effective_focal_length.schema.yml +61 -0
- simtools/schemas/model_parameters/epsg_code.schema.yml +37 -0
- simtools/schemas/model_parameters/fadc_ac_coupled.schema.yml +35 -0
- simtools/schemas/model_parameters/fadc_amplitude.schema.yml +46 -0
- simtools/schemas/model_parameters/fadc_bins.schema.yml +40 -0
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +50 -0
- simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +38 -0
- simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +42 -0
- simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +49 -0
- simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +47 -0
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +51 -0
- simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +37 -0
- simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +43 -0
- simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +49 -0
- simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +43 -0
- simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +39 -0
- simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +42 -0
- simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +40 -0
- simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +50 -0
- simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +42 -0
- simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +41 -0
- simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +42 -0
- simtools/schemas/model_parameters/fadc_max_signal.schema.yml +43 -0
- simtools/schemas/model_parameters/fadc_max_sum.schema.yml +39 -0
- simtools/schemas/model_parameters/fadc_mhz.schema.yml +31 -0
- simtools/schemas/model_parameters/fadc_noise.schema.yml +41 -0
- simtools/schemas/model_parameters/fadc_pedestal.schema.yml +40 -0
- simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +39 -0
- simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +50 -0
- simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +43 -0
- simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +43 -0
- simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +42 -0
- simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +41 -0
- simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +42 -0
- simtools/schemas/model_parameters/flatfielding.schema.yml +37 -0
- simtools/schemas/model_parameters/focal_length.schema.yml +45 -0
- simtools/schemas/model_parameters/focal_surface_parameters.schema.yml +158 -0
- simtools/schemas/model_parameters/focal_surface_ref_radius.schema.yml +29 -0
- simtools/schemas/model_parameters/focus_offset.schema.yml +66 -0
- simtools/schemas/model_parameters/gain_variation.schema.yml +43 -0
- simtools/schemas/model_parameters/geomag_horizontal.schema.yml +34 -0
- simtools/schemas/model_parameters/geomag_rotation.schema.yml +37 -0
- simtools/schemas/model_parameters/geomag_vertical.schema.yml +34 -0
- simtools/schemas/model_parameters/hg_lg_variation.schema.yml +36 -0
- simtools/schemas/model_parameters/iobuf_maximum.schema.yml +34 -0
- simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +34 -0
- simtools/schemas/model_parameters/laser_events.schema.yml +36 -0
- simtools/schemas/model_parameters/laser_external_trigger.schema.yml +35 -0
- simtools/schemas/model_parameters/laser_photons.schema.yml +32 -0
- simtools/schemas/model_parameters/laser_pulse_exptime.schema.yml +34 -0
- simtools/schemas/model_parameters/laser_pulse_offset.schema.yml +34 -0
- simtools/schemas/model_parameters/laser_pulse_sigtime.schema.yml +33 -0
- simtools/schemas/model_parameters/laser_pulse_twidth.schema.yml +33 -0
- simtools/schemas/model_parameters/laser_var_photons.schema.yml +33 -0
- simtools/schemas/model_parameters/laser_wavelength.schema.yml +33 -0
- simtools/schemas/model_parameters/led_events.schema.yml +34 -0
- simtools/schemas/model_parameters/led_photons.schema.yml +34 -0
- simtools/schemas/model_parameters/led_pulse_offset.schema.yml +32 -0
- simtools/schemas/model_parameters/led_pulse_sigtime.schema.yml +33 -0
- simtools/schemas/model_parameters/led_var_photons.schema.yml +34 -0
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +41 -0
- simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +43 -0
- simtools/schemas/model_parameters/min_photoelectrons.schema.yml +35 -0
- simtools/schemas/model_parameters/min_photons.schema.yml +32 -0
- simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +36 -0
- simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +64 -0
- simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +64 -0
- simtools/schemas/model_parameters/mirror_class.schema.yml +41 -0
- simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +51 -0
- simtools/schemas/model_parameters/mirror_focal_length.schema.yml +42 -0
- simtools/schemas/model_parameters/mirror_list.schema.yml +38 -0
- simtools/schemas/model_parameters/mirror_offset.schema.yml +41 -0
- simtools/schemas/model_parameters/mirror_panel_2f_measurements.schema.yml +39 -0
- simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +61 -0
- simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +40 -0
- simtools/schemas/model_parameters/multiplicity_offset.schema.yml +46 -0
- simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +51 -0
- simtools/schemas/model_parameters/nsb_gain_drop_scale.schema.yml +37 -0
- simtools/schemas/model_parameters/nsb_offaxis.schema.yml +79 -0
- simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +47 -0
- simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +34 -0
- simtools/schemas/model_parameters/nsb_reference_value.schema.yml +33 -0
- simtools/schemas/model_parameters/nsb_scaling_factor.schema.yml +35 -0
- simtools/schemas/model_parameters/nsb_skymap.schema.yml +39 -0
- simtools/schemas/model_parameters/nsb_spectrum.schema.yml +50 -0
- simtools/schemas/model_parameters/num_gains.schema.yml +34 -0
- simtools/schemas/model_parameters/only_triggered_telescopes.schema.yml +33 -0
- simtools/schemas/model_parameters/optics_properties.schema.yml +31 -0
- simtools/schemas/model_parameters/parabolic_dish.schema.yml +32 -0
- simtools/schemas/model_parameters/pedestal_events.schema.yml +32 -0
- simtools/schemas/model_parameters/photon_delay.schema.yml +38 -0
- simtools/schemas/model_parameters/photons_per_run.schema.yml +33 -0
- simtools/schemas/model_parameters/pixel_cells.schema.yml +35 -0
- simtools/schemas/model_parameters/pixels_parallel.schema.yml +54 -0
- simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +40 -0
- simtools/schemas/model_parameters/pm_average_gain.schema.yml +34 -0
- simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +40 -0
- simtools/schemas/model_parameters/pm_gain_index.schema.yml +36 -0
- simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +41 -0
- simtools/schemas/model_parameters/pm_transit_time.schema.yml +63 -0
- simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +39 -0
- simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +42 -0
- simtools/schemas/model_parameters/primary_mirror_diameter.schema.yml +33 -0
- simtools/schemas/model_parameters/primary_mirror_hole_diameter.schema.yml +33 -0
- simtools/schemas/model_parameters/primary_mirror_incidence_angle.schema.yml +29 -0
- simtools/schemas/model_parameters/primary_mirror_parameters.schema.yml +168 -0
- simtools/schemas/model_parameters/primary_mirror_ref_radius.schema.yml +36 -0
- simtools/schemas/model_parameters/primary_mirror_segmentation.schema.yml +34 -0
- simtools/schemas/model_parameters/qe_variation.schema.yml +43 -0
- simtools/schemas/model_parameters/quantum_efficiency.schema.yml +42 -0
- simtools/schemas/model_parameters/random_focal_length.schema.yml +45 -0
- simtools/schemas/model_parameters/random_generator.schema.yml +36 -0
- simtools/schemas/model_parameters/reference_point_altitude.schema.yml +35 -0
- simtools/schemas/model_parameters/reference_point_latitude.schema.yml +36 -0
- simtools/schemas/model_parameters/reference_point_longitude.schema.yml +36 -0
- simtools/schemas/model_parameters/reference_point_utm_east.schema.yml +34 -0
- simtools/schemas/model_parameters/reference_point_utm_north.schema.yml +34 -0
- simtools/schemas/model_parameters/sampled_output.schema.yml +31 -0
- simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +34 -0
- simtools/schemas/model_parameters/secondary_mirror_baffle.schema.yml +79 -0
- simtools/schemas/model_parameters/secondary_mirror_degraded_map.schema.yml +42 -0
- simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +41 -0
- simtools/schemas/model_parameters/secondary_mirror_diameter.schema.yml +33 -0
- simtools/schemas/model_parameters/secondary_mirror_hole_diameter.schema.yml +36 -0
- simtools/schemas/model_parameters/secondary_mirror_incidence_angle.schema.yml +29 -0
- simtools/schemas/model_parameters/secondary_mirror_parameters.schema.yml +168 -0
- simtools/schemas/model_parameters/secondary_mirror_ref_radius.schema.yml +36 -0
- simtools/schemas/model_parameters/secondary_mirror_reflectivity.schema.yml +35 -0
- simtools/schemas/model_parameters/secondary_mirror_segmentation.schema.yml +37 -0
- simtools/schemas/model_parameters/secondary_mirror_shadow_diameter.schema.yml +40 -0
- simtools/schemas/model_parameters/secondary_mirror_shadow_offset.schema.yml +40 -0
- simtools/schemas/model_parameters/store_photoelectrons.schema.yml +41 -0
- simtools/schemas/model_parameters/tailcut_scale.schema.yml +40 -0
- simtools/schemas/model_parameters/telescope_axis_height.schema.yml +31 -0
- simtools/schemas/model_parameters/telescope_random_angle.schema.yml +35 -0
- simtools/schemas/model_parameters/telescope_random_error.schema.yml +34 -0
- simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +37 -0
- simtools/schemas/model_parameters/telescope_transmission.schema.yml +113 -0
- simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +41 -0
- simtools/schemas/model_parameters/teltrig_min_time.schema.yml +36 -0
- simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +36 -0
- simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +37 -0
- simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +38 -0
- simtools/schemas/model_parameters/transit_time_error.schema.yml +45 -0
- simtools/schemas/model_parameters/transit_time_jitter.schema.yml +36 -0
- simtools/schemas/model_parameters/trigger_current_limit.schema.yml +32 -0
- simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +53 -0
- simtools/schemas/model_parameters/trigger_pixels.schema.yml +40 -0
- simtools/simtel/simtel_config_reader.py +353 -0
- simtools/simtel/simtel_config_writer.py +244 -63
- simtools/simtel/{simtel_events.py → simtel_io_events.py} +26 -25
- simtools/simtel/simtel_io_histogram.py +661 -0
- simtools/simtel/simtel_io_histograms.py +569 -0
- simtools/simtel/simulator_array.py +145 -0
- simtools/simtel/{simtel_runner_camera_efficiency.py → simulator_camera_efficiency.py} +76 -52
- simtools/simtel/simulator_light_emission.py +473 -0
- simtools/simtel/simulator_ray_tracing.py +262 -0
- simtools/simulator.py +220 -446
- simtools/testing/__init__.py +0 -0
- simtools/testing/assertions.py +151 -0
- simtools/testing/configuration.py +226 -0
- simtools/testing/helpers.py +42 -0
- simtools/testing/validate_output.py +240 -0
- simtools/utils/general.py +340 -437
- simtools/utils/geometry.py +12 -12
- simtools/utils/names.py +257 -644
- simtools/utils/value_conversion.py +176 -0
- simtools/version.py +3 -1
- simtools/visualization/legend_handlers.py +135 -152
- simtools/visualization/plot_camera.py +379 -0
- simtools/visualization/visualize.py +346 -167
- gammasimtools-0.6.1.dist-info/METADATA +0 -180
- gammasimtools-0.6.1.dist-info/RECORD +0 -91
- gammasimtools-0.6.1.dist-info/entry_points.txt +0 -23
- simtools/_dev_version/scm_version.py +0 -10
- simtools/applications/db_development_tools/add_new_parameter_to_db.py +0 -81
- simtools/applications/db_development_tools/add_unit_to_parameter_in_db.py +0 -59
- simtools/applications/db_development_tools/mark_non_optics_parameters_non_applicable.py +0 -102
- simtools/applications/get_parameter.py +0 -92
- simtools/applications/make_regular_arrays.py +0 -160
- simtools/applications/produce_array_config.py +0 -136
- simtools/applications/production.py +0 -313
- simtools/applications/sim_showers_for_trigger_rates.py +0 -187
- simtools/applications/tune_psf.py +0 -334
- simtools/corsika/corsika_default_config.py +0 -282
- simtools/corsika/corsika_runner.py +0 -450
- simtools/corsika_simtel/corsika_simtel_runner.py +0 -197
- simtools/db_handler.py +0 -1480
- simtools/ray_tracing.py +0 -525
- simtools/simtel/simtel_histograms.py +0 -414
- simtools/simtel/simtel_runner.py +0 -244
- simtools/simtel/simtel_runner_array.py +0 -293
- simtools/simtel/simtel_runner_ray_tracing.py +0 -277
- {gammasimtools-0.6.1.dist-info → gammasimtools-0.8.2.dist-info}/LICENSE +0 -0
- {gammasimtools-0.6.1.dist-info → gammasimtools-0.8.2.dist-info}/top_level.txt +0 -0
- /simtools/{corsika_simtel → db}/__init__.py +0 -0
simtools/layout/array_layout.py
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
"""Prepare layout for coordinate transformations."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
1
4
|
import logging
|
|
2
5
|
from pathlib import Path
|
|
3
6
|
|
|
@@ -5,22 +8,23 @@ import astropy.units as u
|
|
|
5
8
|
import numpy as np
|
|
6
9
|
from astropy.table import QTable
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
import simtools.utils.general as gen
|
|
9
12
|
from simtools.data_model import data_reader
|
|
10
13
|
from simtools.io_operations import io_handler
|
|
11
14
|
from simtools.layout.geo_coordinates import GeoCoordinates
|
|
12
15
|
from simtools.layout.telescope_position import TelescopePosition
|
|
13
|
-
from simtools.
|
|
14
|
-
from simtools.
|
|
16
|
+
from simtools.model.site_model import SiteModel
|
|
17
|
+
from simtools.model.telescope_model import TelescopeModel
|
|
18
|
+
from simtools.utils import names, value_conversion
|
|
15
19
|
|
|
16
|
-
__all__ = ["
|
|
20
|
+
__all__ = ["ArrayLayout", "InvalidTelescopeListFileError"]
|
|
17
21
|
|
|
18
22
|
|
|
19
|
-
class
|
|
23
|
+
class InvalidTelescopeListFileError(Exception):
|
|
20
24
|
"""Exception for invalid telescope list file."""
|
|
21
25
|
|
|
22
26
|
|
|
23
|
-
class
|
|
27
|
+
class InvalidCoordinateDataTypeError(Exception):
|
|
24
28
|
"""Exception for low-precision coordinate data type."""
|
|
25
29
|
|
|
26
30
|
|
|
@@ -34,334 +38,139 @@ class ArrayLayout:
|
|
|
34
38
|
MongoDB configuration.
|
|
35
39
|
site: str
|
|
36
40
|
Site name or location (e.g., North/South or LaPalma/Paranal)
|
|
41
|
+
model_version: str
|
|
42
|
+
Version of the model (e.g., 6.0.0).
|
|
37
43
|
label: str
|
|
38
44
|
Instance label.
|
|
39
45
|
name: str
|
|
40
46
|
Name of the layout.
|
|
41
|
-
layout_center_data: dict
|
|
42
|
-
Dict describing array center coordinates.
|
|
43
|
-
corsika_telescope_data: dict
|
|
44
|
-
Dict describing CORSIKA telescope parameters.
|
|
45
47
|
telescope_list_file: str or Path
|
|
46
48
|
Path to the telescope list file.
|
|
49
|
+
telescope_list_metadata_file: str or Path
|
|
50
|
+
Path to telescope list metadata (if not part of telescope_list_file)
|
|
51
|
+
validate: bool
|
|
52
|
+
Validate input file list.
|
|
47
53
|
"""
|
|
48
54
|
|
|
49
55
|
def __init__(
|
|
50
56
|
self,
|
|
51
|
-
mongo_db_config
|
|
52
|
-
site
|
|
57
|
+
mongo_db_config,
|
|
58
|
+
site,
|
|
59
|
+
model_version,
|
|
53
60
|
label=None,
|
|
54
61
|
name=None,
|
|
55
|
-
layout_center_data=None,
|
|
56
|
-
corsika_telescope_data=None,
|
|
57
62
|
telescope_list_file=None,
|
|
58
63
|
telescope_list_metadata_file=None,
|
|
59
64
|
validate=False,
|
|
60
65
|
):
|
|
61
|
-
"""
|
|
62
|
-
Initialize ArrayLayout.
|
|
63
|
-
"""
|
|
64
|
-
|
|
66
|
+
"""Initialize ArrayLayout."""
|
|
65
67
|
self._logger = logging.getLogger(__name__)
|
|
66
68
|
|
|
67
|
-
self.
|
|
69
|
+
self.model_version = model_version
|
|
68
70
|
self.label = label
|
|
69
71
|
self.name = name
|
|
72
|
+
self.mongo_db_config = mongo_db_config
|
|
70
73
|
self.site = None if site is None else names.validate_site_name(site)
|
|
74
|
+
self.site_model = None
|
|
71
75
|
self.io_handler = io_handler.IOHandler()
|
|
72
76
|
self.geo_coordinates = GeoCoordinates()
|
|
73
77
|
|
|
74
|
-
self.telescope_list_file = None
|
|
75
78
|
self._telescope_list = []
|
|
76
|
-
self.
|
|
79
|
+
self._corsika_observation_level = None
|
|
80
|
+
self._reference_position_dict = {}
|
|
81
|
+
self._array_center = None
|
|
77
82
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
self.initialize_array_layout_from_telescope_file(
|
|
83
|
-
telescope_list_file=telescope_list_file,
|
|
84
|
-
telescope_list_metadata_file=telescope_list_metadata_file,
|
|
85
|
-
validate=validate,
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
@classmethod
|
|
89
|
-
def from_array_layout_name(cls, mongo_db_config, array_layout_name, label=None):
|
|
90
|
-
"""
|
|
91
|
-
Read telescope list from file for given layout name (e.g. South-4LST, North-Prod5, ...).
|
|
92
|
-
Layout definitions are given in the `data/layout` path.
|
|
93
|
-
|
|
94
|
-
Parameters
|
|
95
|
-
----------
|
|
96
|
-
mongo_db_config: dict
|
|
97
|
-
MongoDB configuration.
|
|
98
|
-
array_layout_name: str
|
|
99
|
-
e.g. South-4LST, North-Prod5 ...
|
|
100
|
-
label: str
|
|
101
|
-
Instance label. Important for output file naming.
|
|
102
|
-
|
|
103
|
-
Returns
|
|
104
|
-
-------
|
|
105
|
-
ArrayLayout
|
|
106
|
-
Instance of the ArrayLayout.
|
|
107
|
-
"""
|
|
108
|
-
|
|
109
|
-
split_name = array_layout_name.split("-")
|
|
110
|
-
site_name = names.validate_site_name(split_name[0])
|
|
111
|
-
array_name = names.validate_array_layout_name(split_name[1])
|
|
112
|
-
valid_array_layout_name = site_name + "-" + array_name
|
|
113
|
-
|
|
114
|
-
layout = cls(
|
|
115
|
-
site=site_name,
|
|
116
|
-
mongo_db_config=mongo_db_config,
|
|
117
|
-
name=valid_array_layout_name,
|
|
118
|
-
label=label,
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
telescope_list_file = layout.io_handler.get_input_data_file(
|
|
122
|
-
"layout", f"telescope_positions-{valid_array_layout_name}.ecsv"
|
|
83
|
+
self._initialize_array_layout(
|
|
84
|
+
telescope_list_file=telescope_list_file,
|
|
85
|
+
telescope_list_metadata_file=telescope_list_metadata_file,
|
|
86
|
+
validate=validate,
|
|
123
87
|
)
|
|
124
|
-
layout.initialize_array_layout_from_telescope_file(telescope_list_file)
|
|
125
|
-
|
|
126
|
-
return layout
|
|
127
88
|
|
|
128
89
|
def __len__(self):
|
|
129
|
-
"""
|
|
130
|
-
Return number of telescopes in the layout.
|
|
131
|
-
"""
|
|
90
|
+
"""Return number of telescopes in the layout."""
|
|
132
91
|
return len(self._telescope_list)
|
|
133
92
|
|
|
134
93
|
def __getitem__(self, i):
|
|
135
|
-
"""
|
|
136
|
-
Return telescope at list position i.
|
|
137
|
-
|
|
138
|
-
"""
|
|
94
|
+
"""Return telescope at list position i."""
|
|
139
95
|
return self._telescope_list[i]
|
|
140
96
|
|
|
141
|
-
def
|
|
142
|
-
"""
|
|
143
|
-
Initialize
|
|
144
|
-
(dictionary, yaml, ecsv header), which require checks to handle units correctly.
|
|
145
|
-
|
|
146
|
-
Parameters
|
|
147
|
-
----------
|
|
148
|
-
corsika_dict dict
|
|
149
|
-
dictionary with CORSIKA telescope parameters
|
|
150
|
-
|
|
151
|
-
"""
|
|
152
|
-
self._corsika_telescope = {}
|
|
153
|
-
|
|
154
|
-
if corsika_dict is None:
|
|
155
|
-
self._logger.debug("Initialize CORSIKA telescope parameters from file")
|
|
156
|
-
corsika_dict = self._from_corsika_file_to_dict()
|
|
157
|
-
else:
|
|
158
|
-
self._logger.debug(f"Initialize CORSIKA telescope parameters from dict: {corsika_dict}")
|
|
159
|
-
|
|
160
|
-
self._initialize_corsika_telescope_from_dict(corsika_dict)
|
|
161
|
-
|
|
162
|
-
def _from_corsika_file_to_dict(self, file_name=None):
|
|
163
|
-
"""
|
|
164
|
-
Get the corsika parameter file and return a dictionary with the keys necessary to
|
|
165
|
-
initialize this class.
|
|
166
|
-
|
|
167
|
-
Parameters
|
|
168
|
-
----------
|
|
169
|
-
file_name: str or Path
|
|
170
|
-
File from which to extract the corsika parameters. Default is
|
|
171
|
-
data/parameters/corsika_parameters.yml
|
|
172
|
-
|
|
173
|
-
Returns
|
|
174
|
-
------
|
|
175
|
-
corsika_dict:
|
|
176
|
-
Dictionary with corsika telescopes information.
|
|
177
|
-
|
|
178
|
-
Raises
|
|
179
|
-
------
|
|
180
|
-
FileNotFoundError:
|
|
181
|
-
If file_name does not exist.
|
|
182
|
-
"""
|
|
183
|
-
if file_name is None:
|
|
184
|
-
try:
|
|
185
|
-
corsika_parameters_dict = collect_data_from_file_or_dict(
|
|
186
|
-
self.io_handler.get_input_data_file("parameters", "corsika_parameters.yml"),
|
|
187
|
-
None,
|
|
188
|
-
)
|
|
189
|
-
except io_handler.IncompleteIOHandlerInit:
|
|
190
|
-
self._logger.info("Error reading CORSIKA parameters from file")
|
|
191
|
-
return {}
|
|
192
|
-
else:
|
|
193
|
-
if not isinstance(file_name, Path):
|
|
194
|
-
file_name = Path(file_name)
|
|
195
|
-
if file_name.exists():
|
|
196
|
-
corsika_parameters_dict = collect_data_from_file_or_dict(file_name, None)
|
|
197
|
-
else:
|
|
198
|
-
raise FileNotFoundError
|
|
199
|
-
|
|
200
|
-
corsika_dict = {}
|
|
201
|
-
corsika_pars = ["corsika_sphere_radius", "corsika_sphere_center"]
|
|
202
|
-
for simtools_par in corsika_pars:
|
|
203
|
-
corsika_par = names.translate_simtools_to_corsika(simtools_par)
|
|
204
|
-
corsika_dict[simtools_par] = {}
|
|
205
|
-
for key, value in corsika_parameters_dict[corsika_par].items():
|
|
206
|
-
corsika_dict[simtools_par][key] = value["value"]
|
|
207
|
-
try:
|
|
208
|
-
unit = value["unit"]
|
|
209
|
-
corsika_dict[simtools_par][key] = corsika_dict[simtools_par][key] * u.Unit(unit)
|
|
210
|
-
except KeyError:
|
|
211
|
-
self._logger.warning(
|
|
212
|
-
"Key not valid. Dictionary does not have a key 'unit'. Continuing without "
|
|
213
|
-
"the unit."
|
|
214
|
-
)
|
|
215
|
-
|
|
97
|
+
def _initialize_site_parameters_from_db(self):
|
|
98
|
+
"""Initialize site parameters required for transformations using the database."""
|
|
99
|
+
self._logger.debug("Initialize parameters from DB")
|
|
216
100
|
if self.mongo_db_config is None:
|
|
217
|
-
|
|
218
|
-
raise ValueError
|
|
219
|
-
if self.site is None:
|
|
220
|
-
self._logger.error("Site was not provided, cannot set site altitude")
|
|
221
|
-
raise ValueError
|
|
222
|
-
|
|
223
|
-
db = db_handler.DatabaseHandler(mongo_db_config=self.mongo_db_config)
|
|
224
|
-
self._logger.debug("Reading site parameters from DB")
|
|
225
|
-
_site_pars = db.get_site_parameters(self.site, "Released", only_applicable=True)
|
|
226
|
-
corsika_dict["corsika_obs_level"] = _site_pars["altitude"]["Value"] * u.Unit(
|
|
227
|
-
_site_pars["altitude"]["units"]
|
|
228
|
-
)
|
|
229
|
-
|
|
230
|
-
return corsika_dict
|
|
231
|
-
|
|
232
|
-
def _initialize_sphere_parameters(self, sphere_dict):
|
|
233
|
-
"""
|
|
234
|
-
Set CORSIKA sphere parameters from dictionary. Type of input varies and depend on data \
|
|
235
|
-
source for these parameters.
|
|
236
|
-
|
|
237
|
-
Example for sphere_dict: {LST: 12.5 m, MST: 9.15 m, SST: 3 m}
|
|
238
|
-
|
|
239
|
-
Parameters
|
|
240
|
-
----------
|
|
241
|
-
sphere_dict: dict
|
|
242
|
-
dictionary with sphere parameters
|
|
243
|
-
|
|
244
|
-
Returns
|
|
245
|
-
-------
|
|
246
|
-
dict
|
|
247
|
-
dictionary with sphere parameters.
|
|
248
|
-
|
|
249
|
-
"""
|
|
250
|
-
|
|
251
|
-
_sphere_dict_cleaned = {}
|
|
252
|
-
try:
|
|
253
|
-
for key, value in sphere_dict.items():
|
|
254
|
-
if isinstance(value, (str, u.Quantity)):
|
|
255
|
-
_sphere_dict_cleaned[key] = u.Quantity(value)
|
|
256
|
-
else:
|
|
257
|
-
_sphere_dict_cleaned[key] = value["value"] * u.Unit(value["unit"])
|
|
258
|
-
except (TypeError, KeyError) as exc:
|
|
259
|
-
self._logger.error(f"Error setting CORSIKA sphere parameters from {sphere_dict}")
|
|
260
|
-
raise exc
|
|
261
|
-
|
|
262
|
-
return _sphere_dict_cleaned
|
|
101
|
+
raise ValueError("No database configuration provided")
|
|
263
102
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
""
|
|
274
|
-
|
|
275
|
-
try:
|
|
276
|
-
self._corsika_telescope["corsika_obs_level"] = u.Quantity(
|
|
277
|
-
corsika_dict["corsika_obs_level"]
|
|
278
|
-
)
|
|
279
|
-
except (TypeError, KeyError):
|
|
280
|
-
self._corsika_telescope["corsika_obs_level"] = np.nan * u.m
|
|
281
|
-
|
|
282
|
-
for key in ["corsika_sphere_center", "corsika_sphere_radius"]:
|
|
283
|
-
try:
|
|
284
|
-
self._corsika_telescope[key] = self._initialize_sphere_parameters(corsika_dict[key])
|
|
285
|
-
except (TypeError, KeyError):
|
|
286
|
-
pass
|
|
103
|
+
self.site_model = SiteModel(
|
|
104
|
+
site=self.site,
|
|
105
|
+
model_version=self.model_version,
|
|
106
|
+
mongo_db_config=self.mongo_db_config,
|
|
107
|
+
)
|
|
108
|
+
self._corsika_observation_level = self.site_model.get_corsika_site_parameters().get(
|
|
109
|
+
"corsika_observation_level", None
|
|
110
|
+
)
|
|
111
|
+
self._reference_position_dict = self.site_model.get_reference_point()
|
|
112
|
+
self._logger.debug(f"Reference point: {self._reference_position_dict}")
|
|
287
113
|
|
|
288
|
-
def _initialize_coordinate_systems(self
|
|
114
|
+
def _initialize_coordinate_systems(self):
|
|
289
115
|
"""
|
|
290
116
|
Initialize array center and coordinate systems.
|
|
117
|
+
|
|
291
118
|
By definition, the array center is at (0,0) in
|
|
292
119
|
the ground coordinate system.
|
|
293
120
|
|
|
294
|
-
Parameters
|
|
295
|
-
----------
|
|
296
|
-
center_dict: dict
|
|
297
|
-
dictionary with coordinates of array center.
|
|
298
|
-
|
|
299
121
|
Raises
|
|
300
122
|
------
|
|
301
123
|
TypeError
|
|
302
124
|
invalid array center definition.
|
|
303
125
|
|
|
304
126
|
"""
|
|
305
|
-
|
|
306
|
-
center_dict = {} if center_dict is None else center_dict
|
|
307
|
-
|
|
308
127
|
self._array_center = TelescopePosition()
|
|
309
128
|
self._array_center.name = "array_center"
|
|
310
|
-
self._array_center.set_coordinates("ground", 0.0 * u.m, 0.0 * u.m
|
|
311
|
-
self.
|
|
312
|
-
self.
|
|
313
|
-
|
|
314
|
-
|
|
129
|
+
self._array_center.set_coordinates("ground", 0.0 * u.m, 0.0 * u.m)
|
|
130
|
+
self._set_array_center_utm()
|
|
131
|
+
self._array_center.set_altitude(
|
|
132
|
+
u.Quantity(self._reference_position_dict.get("center_altitude", np.nan * u.m))
|
|
133
|
+
)
|
|
134
|
+
_name = self._reference_position_dict.get("array_name")
|
|
315
135
|
self.name = _name if _name is not None else self.name
|
|
316
136
|
|
|
137
|
+
self._logger.debug(f"Initialized array center at UTM {self._reference_position_dict}")
|
|
317
138
|
self._array_center.convert_all(
|
|
318
139
|
crs_local=self.geo_coordinates.crs_local(self._array_center),
|
|
319
140
|
crs_wgs84=self.geo_coordinates.crs_wgs84(),
|
|
320
|
-
crs_utm=self.geo_coordinates.crs_utm(
|
|
141
|
+
crs_utm=self.geo_coordinates.crs_utm(
|
|
142
|
+
self._reference_position_dict.get("epsg_code", None)
|
|
143
|
+
),
|
|
321
144
|
)
|
|
322
145
|
|
|
323
|
-
def
|
|
324
|
-
"""
|
|
325
|
-
Set array center coordinates in mercator system.
|
|
326
|
-
|
|
327
|
-
"""
|
|
328
|
-
|
|
329
|
-
try:
|
|
330
|
-
self._array_center.set_coordinates(
|
|
331
|
-
"mercator",
|
|
332
|
-
u.Quantity(center_dict.get("center_lat", np.nan * u.deg)),
|
|
333
|
-
u.Quantity(center_dict.get("center_lon", np.nan * u.deg)),
|
|
334
|
-
)
|
|
335
|
-
except TypeError:
|
|
336
|
-
pass
|
|
337
|
-
|
|
338
|
-
def _set_array_center_utm(self, center_dict):
|
|
146
|
+
def _set_array_center_utm(self):
|
|
339
147
|
"""
|
|
340
148
|
Set array center coordinates in UTM system.
|
|
149
|
+
|
|
341
150
|
Convert array center position to WGS84 system
|
|
342
151
|
(as latitudes are required for the definition
|
|
343
152
|
for the definition of the ground coordinate system)
|
|
344
153
|
|
|
345
154
|
"""
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
self.
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
self.
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
except TypeError:
|
|
359
|
-
pass
|
|
155
|
+
self._array_center.set_coordinates(
|
|
156
|
+
"utm",
|
|
157
|
+
u.Quantity(self._reference_position_dict.get("center_easting", np.nan * u.m)),
|
|
158
|
+
u.Quantity(self._reference_position_dict.get("center_northing", np.nan * u.m)),
|
|
159
|
+
)
|
|
160
|
+
self._array_center.convert_all(
|
|
161
|
+
crs_local=None,
|
|
162
|
+
crs_wgs84=self.geo_coordinates.crs_wgs84(),
|
|
163
|
+
crs_utm=self.geo_coordinates.crs_utm(
|
|
164
|
+
self._reference_position_dict.get("epsg_code", None)
|
|
165
|
+
),
|
|
166
|
+
)
|
|
360
167
|
|
|
361
|
-
def _altitude_from_corsika_z(self, pos_z=None, altitude=None,
|
|
168
|
+
def _altitude_from_corsika_z(self, pos_z=None, altitude=None, telescope_axis_height=None):
|
|
362
169
|
"""
|
|
363
|
-
Calculate altitude
|
|
364
|
-
|
|
170
|
+
Calculate altitude.
|
|
171
|
+
|
|
172
|
+
The value is calculated from CORSIKA z-coordinate (if pos_z is given) or CORSIKA
|
|
173
|
+
z-coordinate from altitude (if altitude is given).
|
|
365
174
|
|
|
366
175
|
Parameters
|
|
367
176
|
----------
|
|
@@ -369,8 +178,8 @@ class ArrayLayout:
|
|
|
369
178
|
CORSIKA z-coordinate of telescope in equivalent units of meter.
|
|
370
179
|
altitude: astropy.Quantity
|
|
371
180
|
Telescope altitude in equivalent units of meter.
|
|
372
|
-
|
|
373
|
-
Telescope
|
|
181
|
+
tel_axis_height: astropy.Quantity
|
|
182
|
+
Telescope axis height in equivalent units of meter.
|
|
374
183
|
|
|
375
184
|
Returns
|
|
376
185
|
-------
|
|
@@ -378,58 +187,27 @@ class ArrayLayout:
|
|
|
378
187
|
Altitude or CORSIKA z-coordinate (np.nan in case of ill-defined value).
|
|
379
188
|
|
|
380
189
|
"""
|
|
190
|
+
self._logger.debug(
|
|
191
|
+
f"pos_z: {pos_z}, altitude: {altitude}, "
|
|
192
|
+
f"axis_height: {telescope_axis_height}, "
|
|
193
|
+
f"obs_level: {self._corsika_observation_level}"
|
|
194
|
+
)
|
|
195
|
+
|
|
381
196
|
if pos_z is not None and altitude is None:
|
|
382
197
|
return TelescopePosition.convert_telescope_altitude_from_corsika_system(
|
|
383
198
|
pos_z,
|
|
384
|
-
self.
|
|
385
|
-
|
|
199
|
+
self._corsika_observation_level,
|
|
200
|
+
telescope_axis_height,
|
|
386
201
|
)
|
|
387
202
|
|
|
388
203
|
if altitude is not None and pos_z is None:
|
|
389
204
|
return TelescopePosition.convert_telescope_altitude_to_corsika_system(
|
|
390
205
|
altitude,
|
|
391
|
-
self.
|
|
392
|
-
|
|
206
|
+
self._corsika_observation_level,
|
|
207
|
+
telescope_axis_height,
|
|
393
208
|
)
|
|
394
209
|
return np.nan
|
|
395
210
|
|
|
396
|
-
def _get_corsika_sphere_center(self, tel_name):
|
|
397
|
-
"""
|
|
398
|
-
Return CORSIKA sphere center value for given telescope.
|
|
399
|
-
|
|
400
|
-
Parameters
|
|
401
|
-
----------
|
|
402
|
-
tel_name: str
|
|
403
|
-
Telescope Name.
|
|
404
|
-
|
|
405
|
-
Returns
|
|
406
|
-
-------
|
|
407
|
-
astropy.Quantity
|
|
408
|
-
Telescope sphere center value (0.0*u.m if sphere center is not defined).
|
|
409
|
-
|
|
410
|
-
Raises
|
|
411
|
-
------
|
|
412
|
-
KeyError
|
|
413
|
-
if Missing definition of CORSIKA sphere center for this telescope type.
|
|
414
|
-
|
|
415
|
-
"""
|
|
416
|
-
|
|
417
|
-
try:
|
|
418
|
-
return self._corsika_telescope["corsika_sphere_center"][
|
|
419
|
-
names.get_telescope_class(tel_name)
|
|
420
|
-
]
|
|
421
|
-
except KeyError:
|
|
422
|
-
self._logger.warning(
|
|
423
|
-
"Missing definition of CORSIKA sphere center for telescope "
|
|
424
|
-
f"{tel_name} of type {names.get_telescope_class(tel_name)}"
|
|
425
|
-
)
|
|
426
|
-
except ValueError:
|
|
427
|
-
self._logger.warning(
|
|
428
|
-
f"Missing definition of CORSIKA sphere center for telescope {tel_name}"
|
|
429
|
-
)
|
|
430
|
-
|
|
431
|
-
return 0.0 * u.m
|
|
432
|
-
|
|
433
211
|
def _load_telescope_names(self, row):
|
|
434
212
|
"""
|
|
435
213
|
Read and set telescope names.
|
|
@@ -446,17 +224,16 @@ class ArrayLayout:
|
|
|
446
224
|
|
|
447
225
|
Raises
|
|
448
226
|
------
|
|
449
|
-
|
|
227
|
+
InvalidTelescopeListFileError
|
|
450
228
|
in case neither telescope name or asset_code / sequence number are given.
|
|
451
229
|
|
|
452
230
|
"""
|
|
453
|
-
|
|
454
231
|
tel = TelescopePosition()
|
|
455
232
|
try:
|
|
456
233
|
tel.name = row["telescope_name"]
|
|
457
234
|
if "asset_code" not in row:
|
|
458
235
|
try:
|
|
459
|
-
tel.asset_code = names.
|
|
236
|
+
tel.asset_code = names.get_array_element_type_from_name(tel.name)
|
|
460
237
|
# asset code is not a valid telescope name; possibly a calibration device
|
|
461
238
|
except ValueError:
|
|
462
239
|
tel.asset_code = tel.name.split("-")[0]
|
|
@@ -476,39 +253,13 @@ class ArrayLayout:
|
|
|
476
253
|
if tel.name is None:
|
|
477
254
|
msg = "Missing required row with telescope_name or asset_code/sequence_number"
|
|
478
255
|
self._logger.error(msg)
|
|
479
|
-
raise
|
|
256
|
+
raise InvalidTelescopeListFileError(msg)
|
|
480
257
|
|
|
481
258
|
return tel
|
|
482
259
|
|
|
483
|
-
def _assign_unit_to_quantity(self, value, unit):
|
|
484
|
-
"""
|
|
485
|
-
Assign unit to quantity.
|
|
486
|
-
|
|
487
|
-
Parameters
|
|
488
|
-
----------
|
|
489
|
-
value:
|
|
490
|
-
value to get a unit. It can be a float, int, or a Quantity (convertible to 'unit').
|
|
491
|
-
unit: astropy.units.Unit
|
|
492
|
-
Unit to apply to 'quantity'.
|
|
493
|
-
|
|
494
|
-
Returns
|
|
495
|
-
-------
|
|
496
|
-
astropy.units.Quantity
|
|
497
|
-
Quantity of value 'quantity' and unit 'unit'.
|
|
498
|
-
"""
|
|
499
|
-
if isinstance(value, u.Quantity):
|
|
500
|
-
if isinstance(value.unit, type(unit)):
|
|
501
|
-
return value
|
|
502
|
-
try:
|
|
503
|
-
value = value.to(unit)
|
|
504
|
-
return value
|
|
505
|
-
except u.UnitConversionError:
|
|
506
|
-
self._logger.error(f"Cannot convert {value.unit} to {unit}.")
|
|
507
|
-
raise
|
|
508
|
-
return value * unit
|
|
509
|
-
|
|
510
260
|
def _try_set_coordinate(self, row, tel, table, crs_name, key1, key2):
|
|
511
|
-
"""
|
|
261
|
+
"""
|
|
262
|
+
Try and set coordinates for all coordinate systems.
|
|
512
263
|
|
|
513
264
|
Parameters
|
|
514
265
|
----------
|
|
@@ -528,16 +279,17 @@ class ArrayLayout:
|
|
|
528
279
|
try:
|
|
529
280
|
tel.set_coordinates(
|
|
530
281
|
crs_name,
|
|
531
|
-
|
|
532
|
-
|
|
282
|
+
value_conversion.get_value_as_quantity(row[key1], table[key1].unit),
|
|
283
|
+
value_conversion.get_value_as_quantity(row[key2], table[key2].unit),
|
|
533
284
|
)
|
|
534
285
|
except KeyError:
|
|
535
286
|
pass
|
|
536
287
|
|
|
537
288
|
def _try_set_altitude(self, row, tel, table):
|
|
538
289
|
"""
|
|
539
|
-
|
|
540
|
-
|
|
290
|
+
Try and set altitude.
|
|
291
|
+
|
|
292
|
+
It sets the altitude of the TelescopePosition instance.
|
|
541
293
|
|
|
542
294
|
Parameters
|
|
543
295
|
----------
|
|
@@ -551,70 +303,159 @@ class ArrayLayout:
|
|
|
551
303
|
try:
|
|
552
304
|
tel.set_altitude(
|
|
553
305
|
self._altitude_from_corsika_z(
|
|
554
|
-
pos_z=
|
|
306
|
+
pos_z=value_conversion.get_value_as_quantity(
|
|
555
307
|
row["position_z"], table["position_z"].unit
|
|
556
308
|
),
|
|
557
|
-
|
|
309
|
+
telescope_axis_height=tel.get_axis_height(),
|
|
558
310
|
)
|
|
559
311
|
)
|
|
560
312
|
except KeyError:
|
|
561
313
|
pass
|
|
562
314
|
try:
|
|
563
|
-
tel.set_altitude(
|
|
315
|
+
tel.set_altitude(
|
|
316
|
+
value_conversion.get_value_as_quantity(row["altitude"], table["altitude"].unit)
|
|
317
|
+
)
|
|
564
318
|
except KeyError:
|
|
565
319
|
pass
|
|
566
320
|
|
|
567
|
-
def
|
|
321
|
+
def _initialize_array_layout(
|
|
322
|
+
self, telescope_list_file, telescope_list_metadata_file=None, validate=False
|
|
323
|
+
):
|
|
568
324
|
"""
|
|
569
|
-
|
|
325
|
+
Initialize the Layout array including site and telescope parameters.
|
|
326
|
+
|
|
327
|
+
Read array list if telescope_list_file is given.
|
|
570
328
|
|
|
571
329
|
Parameters
|
|
572
330
|
----------
|
|
573
|
-
|
|
574
|
-
|
|
331
|
+
telescope_list_file: str or Path
|
|
332
|
+
Path to the telescope list file.
|
|
333
|
+
telescope_list_metadata_file: str or Path
|
|
334
|
+
Path to the telescope list metadata file.
|
|
335
|
+
validate: bool
|
|
336
|
+
Validate telescope list file against schema.
|
|
575
337
|
|
|
338
|
+
Returns
|
|
339
|
+
-------
|
|
340
|
+
astropy.table.QTable
|
|
341
|
+
Table with the telescope layout information.
|
|
576
342
|
"""
|
|
343
|
+
self._logger.debug("Initializing array (site and telescope parameters)")
|
|
344
|
+
self._initialize_site_parameters_from_db()
|
|
345
|
+
self._initialize_coordinate_systems()
|
|
346
|
+
|
|
347
|
+
if telescope_list_file is None:
|
|
348
|
+
return None
|
|
349
|
+
|
|
350
|
+
self._logger.debug(f"Reading telescope list from {telescope_list_file}")
|
|
351
|
+
if Path(telescope_list_file).suffix == ".json":
|
|
352
|
+
table = self._read_table_from_json_file(file_name=telescope_list_file)
|
|
353
|
+
else:
|
|
354
|
+
table = data_reader.read_table_from_file(
|
|
355
|
+
file_name=telescope_list_file,
|
|
356
|
+
validate=validate,
|
|
357
|
+
metadata_file=telescope_list_metadata_file,
|
|
358
|
+
)
|
|
359
|
+
|
|
577
360
|
for row in table:
|
|
578
361
|
tel = self._load_telescope_names(row)
|
|
362
|
+
if names.get_collection_name_from_array_element_name(tel.name) == "telescopes":
|
|
363
|
+
self._set_telescope_auxiliary_parameters(tel)
|
|
579
364
|
self._try_set_coordinate(row, tel, table, "ground", "position_x", "position_y")
|
|
580
365
|
self._try_set_coordinate(row, tel, table, "utm", "utm_east", "utm_north")
|
|
581
366
|
self._try_set_coordinate(row, tel, table, "mercator", "latitude", "longitude")
|
|
582
367
|
self._try_set_altitude(row, tel, table)
|
|
583
|
-
|
|
584
368
|
self._telescope_list.append(tel)
|
|
585
369
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
):
|
|
370
|
+
return table
|
|
371
|
+
|
|
372
|
+
def _read_table_from_json_file(self, file_name):
|
|
589
373
|
"""
|
|
590
|
-
|
|
374
|
+
Read a telescope position from a json file and return as astropy table.
|
|
591
375
|
|
|
592
376
|
Parameters
|
|
593
377
|
----------
|
|
594
|
-
|
|
595
|
-
Path to the
|
|
596
|
-
telescope_list_metadata_file: str or Path
|
|
597
|
-
Path to the telescope list metadata file.
|
|
598
|
-
validate: bool
|
|
599
|
-
Validate the telescope list file.
|
|
378
|
+
file_name: str or Path
|
|
379
|
+
Path to the json file.
|
|
600
380
|
|
|
601
381
|
Returns
|
|
602
382
|
-------
|
|
603
383
|
astropy.table.QTable
|
|
604
384
|
Table with the telescope layout information.
|
|
605
385
|
"""
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
validate=validate,
|
|
609
|
-
metadata_file=telescope_list_metadata_file,
|
|
610
|
-
)
|
|
611
|
-
self._initialize_corsika_telescope(table.meta)
|
|
612
|
-
self._initialize_coordinate_systems(table.meta)
|
|
613
|
-
self._load_telescope_list(table)
|
|
386
|
+
with Path(file_name).open("r", encoding="utf-8") as file:
|
|
387
|
+
data = json.load(file)
|
|
614
388
|
|
|
389
|
+
position = gen.convert_string_to_list(data["value"])
|
|
390
|
+
self.site = data.get("site", None)
|
|
391
|
+
|
|
392
|
+
table = QTable()
|
|
393
|
+
table["telescope_name"] = [data["instrument"]]
|
|
394
|
+
if "utm" in data["parameter"]:
|
|
395
|
+
table["utm_east"] = [position[0]] * u.Unit(data["unit"])
|
|
396
|
+
table["utm_north"] = [position[1]] * u.Unit(data["unit"])
|
|
397
|
+
table["altitude"] = [position[2]] * u.Unit(data["unit"])
|
|
398
|
+
else:
|
|
399
|
+
table["position_x"] = [position[0]] * u.Unit(data["unit"])
|
|
400
|
+
table["position_y"] = [position[1]] * u.Unit(data["unit"])
|
|
401
|
+
table["position_z"] = [position[2]] * u.Unit(data["unit"])
|
|
615
402
|
return table
|
|
616
403
|
|
|
617
|
-
def
|
|
404
|
+
def _get_telescope_model(self, telescope_name):
|
|
405
|
+
"""
|
|
406
|
+
Get telescope model from the database.
|
|
407
|
+
|
|
408
|
+
Parameters
|
|
409
|
+
----------
|
|
410
|
+
telescope_name: str
|
|
411
|
+
Name of the telescope.
|
|
412
|
+
|
|
413
|
+
Returns
|
|
414
|
+
-------
|
|
415
|
+
TelescopeModel
|
|
416
|
+
Telescope model instance.
|
|
417
|
+
"""
|
|
418
|
+
return TelescopeModel(
|
|
419
|
+
site=self.site,
|
|
420
|
+
telescope_name=telescope_name,
|
|
421
|
+
model_version=self.model_version,
|
|
422
|
+
mongo_db_config=self.mongo_db_config,
|
|
423
|
+
label=self.label,
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
def _set_telescope_auxiliary_parameters(self, telescope, telescope_name=None):
|
|
427
|
+
"""
|
|
428
|
+
Set auxiliary CORSIKA parameters for a telescope.
|
|
429
|
+
|
|
430
|
+
Uses as default the design model if telescope is not found in the database.
|
|
431
|
+
|
|
432
|
+
Parameters
|
|
433
|
+
----------
|
|
434
|
+
telescope: TelescopePosition
|
|
435
|
+
Instance of TelescopePosition.
|
|
436
|
+
|
|
437
|
+
"""
|
|
438
|
+
telescope_name = telescope_name if telescope_name is not None else telescope.name
|
|
439
|
+
if names.get_collection_name_from_array_element_name(telescope_name) == "telescopes":
|
|
440
|
+
self._logger.debug(
|
|
441
|
+
f"Reading auxiliary telescope parameters for {telescope_name}"
|
|
442
|
+
f" (model version {self.model_version})"
|
|
443
|
+
)
|
|
444
|
+
try:
|
|
445
|
+
tel_model = self._get_telescope_model(telescope_name)
|
|
446
|
+
except ValueError:
|
|
447
|
+
tel_model = self._get_telescope_model(
|
|
448
|
+
names.get_array_element_type_from_name(telescope_name) + "-design",
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
for para in ("telescope_axis_height", "telescope_sphere_radius"):
|
|
452
|
+
telescope.set_auxiliary_parameter(
|
|
453
|
+
para, tel_model.get_parameter_value_with_unit(para)
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
def add_telescope(
|
|
457
|
+
self, telescope_name, crs_name, xx, yy, altitude=None, tel_corsika_z=None, design_model=None
|
|
458
|
+
):
|
|
618
459
|
"""
|
|
619
460
|
Add an individual telescope to the telescope list.
|
|
620
461
|
|
|
@@ -633,25 +474,28 @@ class ArrayLayout:
|
|
|
633
474
|
tel_corsika_z: astropy.units.quantity.Quantity
|
|
634
475
|
CORSIKA z-position (requires setting of CORSIKA observation level and telescope sphere\
|
|
635
476
|
center).
|
|
477
|
+
design_model: str
|
|
478
|
+
Name of the design model (optional).
|
|
479
|
+
If none, telescope type + "-design" is used.
|
|
636
480
|
"""
|
|
637
|
-
|
|
638
481
|
tel = TelescopePosition(name=telescope_name)
|
|
482
|
+
self._set_telescope_auxiliary_parameters(tel, design_model)
|
|
639
483
|
tel.set_coordinates(crs_name, xx, yy)
|
|
640
484
|
if altitude is not None:
|
|
641
485
|
tel.set_altitude(altitude)
|
|
642
486
|
elif tel_corsika_z is not None:
|
|
643
|
-
tel.set_altitude(
|
|
487
|
+
tel.set_altitude(
|
|
488
|
+
self._altitude_from_corsika_z(
|
|
489
|
+
pos_z=tel_corsika_z, telescope_axis_height=tel.get_axis_height()
|
|
490
|
+
)
|
|
491
|
+
)
|
|
644
492
|
self._telescope_list.append(tel)
|
|
645
493
|
|
|
646
|
-
def _get_export_metadata(self
|
|
494
|
+
def _get_export_metadata(self):
|
|
647
495
|
"""
|
|
648
|
-
File metadata for export of array element list to file.
|
|
649
|
-
CORSIKA telescope parameters, and EPSG center
|
|
496
|
+
File metadata for export of array element list to file.
|
|
650
497
|
|
|
651
|
-
|
|
652
|
-
----------
|
|
653
|
-
export_corsika_meta: bool
|
|
654
|
-
write CORSIKA metadata.
|
|
498
|
+
Included array center definition, CORSIKA telescope parameters, and EPSG code.
|
|
655
499
|
|
|
656
500
|
Returns
|
|
657
501
|
-------
|
|
@@ -659,31 +503,19 @@ class ArrayLayout:
|
|
|
659
503
|
Metadata header for array element list export.
|
|
660
504
|
|
|
661
505
|
"""
|
|
662
|
-
|
|
663
|
-
_meta = {
|
|
664
|
-
"center_lon": None,
|
|
665
|
-
"center_lat": None,
|
|
666
|
-
"center_northing": None,
|
|
667
|
-
"center_easting": None,
|
|
668
|
-
"center_alt": None,
|
|
669
|
-
}
|
|
506
|
+
_meta = {}
|
|
670
507
|
if self._array_center:
|
|
671
|
-
_meta["center_lat"], _meta["center_lon"], _ = self._array_center.get_coordinates(
|
|
672
|
-
"mercator"
|
|
673
|
-
)
|
|
674
508
|
(
|
|
675
509
|
_meta["center_easting"],
|
|
676
510
|
_meta["center_northing"],
|
|
677
|
-
_meta["
|
|
511
|
+
_meta["center_altitude"],
|
|
678
512
|
) = self._array_center.get_coordinates("utm")
|
|
679
|
-
|
|
680
|
-
_meta.update(self._corsika_telescope)
|
|
681
|
-
_meta["EPSG"] = self._epsg
|
|
513
|
+
_meta["epsg_code"] = self._reference_position_dict.get("epsg_code", None)
|
|
682
514
|
_meta["array_name"] = self.name
|
|
683
515
|
|
|
684
516
|
return _meta
|
|
685
517
|
|
|
686
|
-
def export_telescope_list_table(self, crs_name
|
|
518
|
+
def export_telescope_list_table(self, crs_name):
|
|
687
519
|
"""
|
|
688
520
|
Export array elements positions to astropy table.
|
|
689
521
|
|
|
@@ -691,31 +523,31 @@ class ArrayLayout:
|
|
|
691
523
|
----------
|
|
692
524
|
crs_name: str
|
|
693
525
|
Name of coordinate system to be used for export.
|
|
694
|
-
corsika_z: bool
|
|
695
|
-
Write telescope height in CORSIKA coordinates (for CORSIKA system).
|
|
696
526
|
|
|
697
527
|
Returns
|
|
698
528
|
-------
|
|
699
529
|
astropy.table.QTable
|
|
700
530
|
Astropy table with the telescope layout information.
|
|
701
|
-
|
|
702
531
|
"""
|
|
703
|
-
|
|
704
|
-
table = QTable(meta=self._get_export_metadata(crs_name == "ground"))
|
|
532
|
+
table = QTable(meta=self._get_export_metadata())
|
|
705
533
|
|
|
706
534
|
tel_names, asset_code, sequence_number, geo_code = [], [], [], []
|
|
707
|
-
pos_x, pos_y, pos_z = [], [], []
|
|
535
|
+
pos_x, pos_y, pos_z, pos_t, tel_r = [], [], [], [], []
|
|
708
536
|
for tel in self._telescope_list:
|
|
709
537
|
tel_names.append(tel.name)
|
|
710
538
|
asset_code.append(tel.asset_code)
|
|
711
539
|
sequence_number.append(tel.sequence_number)
|
|
712
540
|
geo_code.append(tel.geo_code)
|
|
713
541
|
x, y, z = tel.get_coordinates(crs_name)
|
|
714
|
-
if
|
|
715
|
-
z = self._altitude_from_corsika_z(
|
|
542
|
+
if crs_name == "ground":
|
|
543
|
+
z = self._altitude_from_corsika_z(
|
|
544
|
+
altitude=z, telescope_axis_height=tel.get_axis_height()
|
|
545
|
+
)
|
|
546
|
+
pos_t.append(tel.get_axis_height())
|
|
716
547
|
pos_x.append(x)
|
|
717
548
|
pos_y.append(y)
|
|
718
549
|
pos_z.append(z)
|
|
550
|
+
tel_r.append(tel.get_sphere_radius())
|
|
719
551
|
|
|
720
552
|
# prefer asset_code / sequence_number of telescope_name
|
|
721
553
|
if all(v is not None for v in asset_code) and all(v is not None for v in sequence_number):
|
|
@@ -732,137 +564,115 @@ class ArrayLayout:
|
|
|
732
564
|
)
|
|
733
565
|
table[_name_x] = pos_x
|
|
734
566
|
table[_name_y] = pos_y
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
567
|
+
table[_name_z] = pos_z
|
|
568
|
+
if len(pos_t) > 0:
|
|
569
|
+
table["telescope_axis_height"] = pos_t
|
|
570
|
+
if len(tel_r) > 0:
|
|
571
|
+
table["sphere_radius"] = tel_r
|
|
739
572
|
except IndexError:
|
|
740
573
|
pass
|
|
741
574
|
|
|
575
|
+
if "telescope_name" in table.colnames:
|
|
576
|
+
table.sort("telescope_name")
|
|
577
|
+
if "asset_code" in table.colnames:
|
|
578
|
+
table.sort(["asset_code", "sequence_number"])
|
|
579
|
+
|
|
742
580
|
return table
|
|
743
581
|
|
|
744
|
-
def
|
|
582
|
+
def export_one_telescope_as_json(self, crs_name):
|
|
745
583
|
"""
|
|
746
|
-
Return
|
|
584
|
+
Return a list containing a single telescope in simtools-DB-style json.
|
|
585
|
+
|
|
586
|
+
Parameters
|
|
587
|
+
----------
|
|
588
|
+
crs_name: str
|
|
589
|
+
Name of coordinate system to be used for export.
|
|
747
590
|
|
|
748
591
|
Returns
|
|
749
592
|
-------
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
"""
|
|
753
|
-
|
|
593
|
+
dict
|
|
594
|
+
Dictionary with array element information.
|
|
595
|
+
"""
|
|
596
|
+
table = self.export_telescope_list_table(crs_name)
|
|
597
|
+
if len(table) != 1:
|
|
598
|
+
raise ValueError("Only one telescope can be exported to json")
|
|
599
|
+
parameter_name = value_string = None
|
|
600
|
+
if crs_name == "ground":
|
|
601
|
+
parameter_name = "array_element_position_ground"
|
|
602
|
+
value_string = gen.convert_list_to_string(
|
|
603
|
+
[
|
|
604
|
+
table["position_x"][0].value,
|
|
605
|
+
table["position_y"][0].value,
|
|
606
|
+
table["position_z"][0].value,
|
|
607
|
+
]
|
|
608
|
+
)
|
|
609
|
+
elif crs_name == "utm":
|
|
610
|
+
parameter_name = "array_element_position_utm"
|
|
611
|
+
value_string = gen.convert_list_to_string(
|
|
612
|
+
[
|
|
613
|
+
table["utm_east"][0].value,
|
|
614
|
+
table["utm_north"][0].value,
|
|
615
|
+
table["altitude"][0].value,
|
|
616
|
+
]
|
|
617
|
+
)
|
|
618
|
+
elif crs_name == "mercator":
|
|
619
|
+
parameter_name = "array_element_position_mercator"
|
|
620
|
+
value_string = gen.convert_list_to_string(
|
|
621
|
+
[
|
|
622
|
+
table["latitude"][0].value,
|
|
623
|
+
table["longitude"][0].value,
|
|
624
|
+
table["altitude"][0].value,
|
|
625
|
+
]
|
|
626
|
+
)
|
|
627
|
+
return {
|
|
628
|
+
"parameter": parameter_name,
|
|
629
|
+
"instrument": table["telescope_name"][0],
|
|
630
|
+
"site": self.site,
|
|
631
|
+
"version": self.model_version,
|
|
632
|
+
"value": value_string,
|
|
633
|
+
"unit": "m",
|
|
634
|
+
"type": "float64",
|
|
635
|
+
"applicable": True,
|
|
636
|
+
"file": False,
|
|
637
|
+
}
|
|
754
638
|
|
|
755
|
-
def
|
|
639
|
+
def get_number_of_telescopes(self):
|
|
756
640
|
"""
|
|
757
|
-
|
|
641
|
+
Return the number of telescopes in the list.
|
|
758
642
|
|
|
759
643
|
Returns
|
|
760
644
|
-------
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
Raises
|
|
765
|
-
------
|
|
766
|
-
KeyError
|
|
767
|
-
if Missing definition of CORSIKA sphere radius or obs_level.
|
|
768
|
-
"""
|
|
769
|
-
|
|
770
|
-
corsika_list = ""
|
|
771
|
-
for tel in self._telescope_list:
|
|
772
|
-
pos_x, pos_y, pos_z = tel.get_coordinates("ground")
|
|
773
|
-
try:
|
|
774
|
-
sphere_radius = self._corsika_telescope["corsika_sphere_radius"][
|
|
775
|
-
names.get_telescope_class(tel.name)
|
|
776
|
-
]
|
|
777
|
-
except KeyError:
|
|
778
|
-
self._logger.error("Missing definition of CORSIKA sphere radius")
|
|
779
|
-
raise
|
|
780
|
-
try:
|
|
781
|
-
pos_z = tel.convert_telescope_altitude_to_corsika_system(
|
|
782
|
-
pos_z,
|
|
783
|
-
self._corsika_telescope["corsika_obs_level"],
|
|
784
|
-
self._get_corsika_sphere_center(tel.name),
|
|
785
|
-
)
|
|
786
|
-
except KeyError:
|
|
787
|
-
self._logger.error("Missing definition of CORSIKA sphere center / obs_level")
|
|
788
|
-
raise
|
|
789
|
-
|
|
790
|
-
corsika_list += "TELESCOPE"
|
|
791
|
-
for pos in [pos_x, pos_y, pos_z]:
|
|
792
|
-
corsika_list += f"\t {pos.value:.3f}E2"
|
|
793
|
-
corsika_list += f"\t {sphere_radius.value:.3f}E2"
|
|
794
|
-
corsika_list += f"\t # {tel.name}\n"
|
|
795
|
-
|
|
796
|
-
return corsika_list
|
|
797
|
-
|
|
798
|
-
def _print_all(self):
|
|
799
|
-
""" "
|
|
800
|
-
Print all columns for all coordinate systems.
|
|
801
|
-
|
|
645
|
+
int
|
|
646
|
+
Number of telescopes.
|
|
802
647
|
"""
|
|
648
|
+
return len(self._telescope_list)
|
|
803
649
|
|
|
804
|
-
|
|
805
|
-
print("ArrayCenter")
|
|
806
|
-
print(self._array_center)
|
|
807
|
-
print("Telescopes")
|
|
808
|
-
for tel in self._telescope_list:
|
|
809
|
-
print(tel)
|
|
810
|
-
|
|
811
|
-
def _print_compact(self, compact_printing, corsika_z=False):
|
|
650
|
+
def print_telescope_list(self, crs_name):
|
|
812
651
|
"""
|
|
813
|
-
|
|
814
|
-
|
|
652
|
+
Print list of telescopes.
|
|
815
653
|
|
|
816
654
|
Parameters
|
|
817
655
|
----------
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
printed, if compact_printing is None.
|
|
821
|
-
corsika_z: bool
|
|
822
|
-
Print telescope height in CORSIKA coordinates (for CORSIKA system)
|
|
656
|
+
crs_name: str
|
|
657
|
+
Name of coordinate system to be used for export.
|
|
823
658
|
|
|
824
659
|
"""
|
|
825
|
-
|
|
826
660
|
for tel in self._telescope_list:
|
|
827
|
-
if corsika_z:
|
|
828
|
-
_corsika_obs_level = self._corsika_telescope["corsika_obs_level"]
|
|
829
|
-
_corsika_sphere_center = self._get_corsika_sphere_center(tel.name)
|
|
830
|
-
else:
|
|
831
|
-
_corsika_obs_level = None
|
|
832
|
-
_corsika_sphere_center = None
|
|
833
|
-
|
|
834
661
|
tel.print_compact_format(
|
|
835
|
-
crs_name=
|
|
662
|
+
crs_name=crs_name,
|
|
836
663
|
print_header=(tel == self._telescope_list[0]),
|
|
837
|
-
|
|
838
|
-
|
|
664
|
+
corsika_observation_level=(
|
|
665
|
+
self._corsika_observation_level if crs_name == "ground" else None
|
|
666
|
+
),
|
|
839
667
|
)
|
|
840
668
|
|
|
841
|
-
def print_telescope_list(self, compact_printing="", corsika_z=False):
|
|
842
|
-
"""
|
|
843
|
-
Print list of telescopes in latest released layout.
|
|
844
|
-
|
|
845
|
-
Parameters
|
|
846
|
-
----------
|
|
847
|
-
compact_printing: str
|
|
848
|
-
Compact printout for a single coordinate system.
|
|
849
|
-
corsika_z: bool
|
|
850
|
-
Print telescope height in CORSIKA coordinates (for CORSIKA system).
|
|
851
|
-
"""
|
|
852
|
-
|
|
853
|
-
if len(compact_printing) == 0:
|
|
854
|
-
self._print_all()
|
|
855
|
-
else:
|
|
856
|
-
self._print_compact(compact_printing, corsika_z)
|
|
857
|
-
|
|
858
669
|
def convert_coordinates(self):
|
|
859
670
|
"""Perform all the possible conversions the coordinates of the tel positions."""
|
|
860
|
-
|
|
861
671
|
self._logger.info("Converting telescope coordinates")
|
|
862
672
|
|
|
863
673
|
crs_wgs84 = self.geo_coordinates.crs_wgs84()
|
|
864
674
|
crs_local = self.geo_coordinates.crs_local(self._array_center)
|
|
865
|
-
crs_utm = self.geo_coordinates.crs_utm(self.
|
|
675
|
+
crs_utm = self.geo_coordinates.crs_utm(self._reference_position_dict.get("epsg_code", None))
|
|
866
676
|
|
|
867
677
|
for tel in self._telescope_list:
|
|
868
678
|
tel.convert_all(
|
|
@@ -871,35 +681,6 @@ class ArrayLayout:
|
|
|
871
681
|
crs_utm=crs_utm,
|
|
872
682
|
)
|
|
873
683
|
|
|
874
|
-
@staticmethod
|
|
875
|
-
def include_radius_into_telescope_table(telescope_table):
|
|
876
|
-
"""
|
|
877
|
-
Include the radius of the telescopes types into the astropy.table.QTable telescopes_table
|
|
878
|
-
|
|
879
|
-
Parameters
|
|
880
|
-
----------
|
|
881
|
-
telescope_table: astropy.QTable
|
|
882
|
-
Astropy QTable with telescope information.
|
|
883
|
-
|
|
884
|
-
Returns
|
|
885
|
-
-------
|
|
886
|
-
astropy.QTable
|
|
887
|
-
Astropy QTable with telescope information updated with the radius.
|
|
888
|
-
"""
|
|
889
|
-
|
|
890
|
-
telescope_table["radius"] = [
|
|
891
|
-
u.Quantity(
|
|
892
|
-
telescope_table.meta["corsika_sphere_radius"][
|
|
893
|
-
names.get_telescope_class(tel_name_now)
|
|
894
|
-
]
|
|
895
|
-
)
|
|
896
|
-
.to("m")
|
|
897
|
-
.value
|
|
898
|
-
for tel_name_now in telescope_table["telescope_name"]
|
|
899
|
-
]
|
|
900
|
-
telescope_table["radius"] = telescope_table["radius"].quantity * u.m
|
|
901
|
-
return telescope_table
|
|
902
|
-
|
|
903
684
|
def select_assets(self, asset_list=None):
|
|
904
685
|
"""
|
|
905
686
|
Select a subsets of telescopes / assets from the layout.
|
|
@@ -907,7 +688,7 @@ class ArrayLayout:
|
|
|
907
688
|
Parameters
|
|
908
689
|
----------
|
|
909
690
|
asset_list: list
|
|
910
|
-
List of assets to be selected
|
|
691
|
+
List of assets to be selected (telescope names or types)
|
|
911
692
|
|
|
912
693
|
Raises
|
|
913
694
|
------
|
|
@@ -915,13 +696,20 @@ class ArrayLayout:
|
|
|
915
696
|
If the asset list is empty.
|
|
916
697
|
|
|
917
698
|
"""
|
|
918
|
-
|
|
919
699
|
_n_telescopes = len(self._telescope_list)
|
|
920
700
|
try:
|
|
921
701
|
if len(asset_list) > 0:
|
|
922
|
-
|
|
702
|
+
_telescope_list_from_name = [
|
|
923
703
|
tel for tel in self._telescope_list if tel.asset_code in asset_list
|
|
924
704
|
]
|
|
705
|
+
_telescope_list_from_type = [
|
|
706
|
+
tel
|
|
707
|
+
for tel in self._telescope_list
|
|
708
|
+
if names.get_array_element_type_from_name(tel.asset_code) in asset_list
|
|
709
|
+
]
|
|
710
|
+
self._telescope_list = list(
|
|
711
|
+
set(_telescope_list_from_name + _telescope_list_from_type)
|
|
712
|
+
)
|
|
925
713
|
self._logger.info(
|
|
926
714
|
f"Selected {len(self._telescope_list)} telescopes"
|
|
927
715
|
f" (from originally {_n_telescopes})"
|