gammasimtools 0.18.0__py3-none-any.whl → 0.20.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.18.0.dist-info → gammasimtools-0.20.0.dist-info}/METADATA +24 -69
- gammasimtools-0.20.0.dist-info/RECORD +395 -0
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/entry_points.txt +11 -4
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/licenses/LICENSE +1 -1
- simtools/_version.py +16 -3
- simtools/applications/calculate_incident_angles.py +182 -0
- simtools/applications/convert_all_model_parameters_from_simtel.py +4 -3
- simtools/applications/convert_geo_coordinates_of_array_elements.py +3 -3
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +17 -14
- simtools/applications/db_add_value_from_json_to_db.py +8 -10
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +8 -13
- simtools/applications/db_generate_compound_indexes.py +65 -0
- simtools/applications/db_get_file_from_db.py +12 -24
- simtools/applications/db_get_parameter_from_db.py +4 -4
- simtools/applications/db_inspect_databases.py +20 -10
- simtools/applications/derive_mirror_rnda.py +17 -11
- simtools/applications/derive_psf_parameters.py +59 -309
- simtools/applications/derive_trigger_rates.py +91 -0
- simtools/applications/docs_produce_array_element_report.py +1 -1
- simtools/applications/docs_produce_calibration_reports.py +1 -1
- simtools/applications/docs_produce_model_parameter_reports.py +1 -1
- simtools/applications/docs_produce_simulation_configuration_report.py +1 -1
- simtools/applications/generate_corsika_histograms.py +1 -1
- simtools/applications/generate_default_metadata.py +8 -24
- simtools/applications/generate_simtel_event_data.py +11 -11
- simtools/applications/maintain_simulation_model_add_production_table.py +71 -0
- simtools/applications/maintain_simulation_model_compare_productions.py +98 -0
- simtools/applications/{verify_simulation_model_production_tables.py → maintain_simulation_model_verify_production_tables.py} +9 -1
- simtools/applications/merge_tables.py +2 -2
- simtools/applications/plot_array_layout.py +3 -3
- simtools/applications/plot_simtel_events.py +421 -0
- simtools/applications/plot_tabular_data.py +9 -2
- simtools/applications/plot_tabular_data_for_model_parameter.py +2 -1
- simtools/applications/print_version.py +8 -9
- simtools/applications/production_derive_corsika_limits.py +6 -7
- simtools/applications/production_derive_statistics.py +1 -1
- simtools/applications/production_generate_grid.py +2 -2
- simtools/applications/production_merge_corsika_limits.py +214 -0
- simtools/applications/run_application.py +47 -113
- simtools/applications/simulate_calibration_events.py +166 -0
- simtools/applications/simulate_flasher.py +141 -0
- simtools/applications/{simulate_light_emission.py → simulate_illuminator.py} +35 -99
- simtools/applications/simulate_prod.py +6 -24
- simtools/applications/simulate_prod_htcondor_generator.py +7 -0
- simtools/applications/submit_array_layouts.py +2 -1
- simtools/applications/submit_model_parameter_from_external.py +1 -1
- simtools/applications/validate_camera_efficiency.py +30 -12
- simtools/applications/validate_camera_fov.py +1 -1
- simtools/applications/validate_cumulative_psf.py +1 -1
- simtools/applications/validate_file_using_schema.py +9 -5
- simtools/applications/validate_optics.py +1 -1
- simtools/camera/camera_efficiency.py +61 -45
- simtools/camera/single_photon_electron_spectrum.py +1 -1
- simtools/configuration/commandline_parser.py +46 -11
- simtools/configuration/configurator.py +4 -4
- simtools/corsika/corsika_config.py +45 -25
- simtools/corsika/corsika_histograms.py +6 -5
- simtools/data_model/data_reader.py +2 -3
- simtools/data_model/metadata_collector.py +32 -36
- simtools/data_model/metadata_model.py +15 -12
- simtools/data_model/model_data_writer.py +13 -32
- simtools/data_model/schema.py +74 -24
- simtools/data_model/validate_data.py +42 -12
- simtools/db/db_handler.py +125 -62
- simtools/db/db_model_upload.py +14 -19
- simtools/dependencies.py +98 -30
- simtools/io/ascii_handler.py +279 -0
- simtools/{io_operations → io}/io_handler.py +25 -3
- simtools/job_execution/htcondor_script_generator.py +15 -4
- simtools/layout/array_layout.py +1 -1
- simtools/layout/array_layout_utils.py +51 -12
- simtools/model/array_model.py +41 -5
- simtools/model/flasher_model.py +106 -0
- simtools/model/model_parameter.py +4 -4
- simtools/model/model_repository.py +197 -2
- simtools/model/site_model.py +25 -0
- simtools/model/telescope_model.py +3 -1
- simtools/production_configuration/derive_corsika_limits.py +336 -427
- simtools/production_configuration/derive_production_statistics_handler.py +7 -6
- simtools/production_configuration/generate_production_grid.py +9 -11
- simtools/production_configuration/merge_corsika_limits.py +528 -0
- simtools/ray_tracing/incident_angles.py +706 -0
- simtools/ray_tracing/mirror_panel_psf.py +1 -0
- simtools/ray_tracing/psf_parameter_optimisation.py +792 -0
- simtools/ray_tracing/ray_tracing.py +6 -2
- simtools/reporting/docs_read_parameters.py +150 -62
- simtools/runners/corsika_runner.py +1 -1
- simtools/runners/corsika_simtel_runner.py +14 -5
- simtools/runners/runner_services.py +10 -5
- simtools/runners/simtools_runner.py +267 -0
- simtools/schemas/application_workflow.metaschema.yml +101 -68
- simtools/schemas/input/MST_mirror_2f_measurements.schema.yml +1 -1
- simtools/schemas/input/single_pe_spectrum.schema.yml +1 -1
- simtools/schemas/metadata.metaschema.yml +577 -3
- simtools/schemas/model_parameter.metaschema.yml +6 -6
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +4 -4
- simtools/schemas/model_parameters/adjust_gain.schema.yml +1 -1
- simtools/schemas/model_parameters/altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/array_coordinates.schema.yml +1 -1
- simtools/schemas/model_parameters/array_coordinates_UTM.schema.yml +1 -1
- simtools/schemas/model_parameters/array_element_position_ground.schema.yml +1 -1
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +1 -1
- simtools/schemas/model_parameters/array_layouts.schema.yml +1 -1
- simtools/schemas/model_parameters/array_triggers.schema.yml +1 -1
- simtools/schemas/model_parameters/array_window.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_shaping.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/atmospheric_profile.schema.yml +1 -1
- simtools/schemas/model_parameters/atmospheric_transmission.schema.yml +1 -1
- simtools/schemas/model_parameters/axes_offsets.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_body_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_body_shape.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_config_file.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_config_rotate.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_depth.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_filter.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_filter_incidence_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_pixels.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_transmission.schema.yml +1 -1
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
- simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_cherenkov_photon_bunch_size.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_cherenkov_photon_wavelength_range.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_first_interaction_height.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_longitudinal_shower_development.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_observation_level.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_particle_kinetic_energy_cutoff.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +3 -3
- simtools/schemas/model_parameters/dark_events.schema.yml +1 -1
- simtools/schemas/model_parameters/default_trigger.schema.yml +1 -1
- simtools/schemas/model_parameters/design_model.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_ac_coupled.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_start.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/dish_shape_length.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_pedsub.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +1 -1
- simtools/schemas/model_parameters/effective_focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/epsg_code.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_ac_coupled.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_long_event_threshold.schema.yml +35 -0
- simtools/schemas/model_parameters/fadc_long_sum_bins.schema.yml +41 -0
- simtools/schemas/model_parameters/fadc_long_sum_offset.schema.yml +38 -0
- simtools/schemas/model_parameters/fadc_max_signal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_max_sum.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_mhz.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_noise.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fake_mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/flatfielding.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_surface_parameters.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_surface_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/focus_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/gain_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_horizontal.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_rotation.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_vertical.schema.yml +1 -1
- simtools/schemas/model_parameters/hg_lg_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_events.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_external_trigger.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_exptime.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_sigtime.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_twidth.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_var_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_wavelength.schema.yml +1 -1
- simtools/schemas/model_parameters/led_events.schema.yml +1 -1
- simtools/schemas/model_parameters/led_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/led_pulse_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/led_pulse_sigtime.schema.yml +1 -1
- simtools/schemas/model_parameters/led_var_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +50 -1
- simtools/schemas/model_parameters/min_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/min_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_class.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_panel_2f_measurements.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +1 -1
- simtools/schemas/model_parameters/multiplicity_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/muon_mono_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_gain_drop_scale.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_offaxis.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +2 -2
- simtools/schemas/model_parameters/nsb_reference_value.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_scaling_factor.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_sky_map.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_spectrum.schema.yml +23 -30
- simtools/schemas/model_parameters/num_gains.schema.yml +1 -1
- simtools/schemas/model_parameters/only_triggered_telescopes.schema.yml +1 -1
- simtools/schemas/model_parameters/optics_properties.schema.yml +1 -1
- simtools/schemas/model_parameters/parabolic_dish.schema.yml +1 -1
- simtools/schemas/model_parameters/pedestal_events.schema.yml +1 -1
- simtools/schemas/model_parameters/photon_delay.schema.yml +1 -1
- simtools/schemas/model_parameters/photons_per_run.schema.yml +1 -1
- simtools/schemas/model_parameters/pixel_cells.schema.yml +1 -1
- simtools/schemas/model_parameters/pixels_parallel.schema.yml +1 -1
- simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_average_gain.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_gain_index.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_transit_time.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_hole_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_incidence_angle.schema.yml +11 -1
- simtools/schemas/model_parameters/primary_mirror_parameters.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_segmentation.schema.yml +1 -1
- simtools/schemas/model_parameters/qe_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/quantum_efficiency.schema.yml +1 -1
- simtools/schemas/model_parameters/random_focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/random_generator.schema.yml +1 -1
- simtools/schemas/model_parameters/random_mono_probability.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_latitude.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_longitude.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_utm_east.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_utm_north.schema.yml +1 -1
- simtools/schemas/model_parameters/sampled_output.schema.yml +1 -1
- simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_baffle.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_hole_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_incidence_angle.schema.yml +11 -1
- simtools/schemas/model_parameters/secondary_mirror_parameters.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_reflectivity.schema.yml +11 -1
- simtools/schemas/model_parameters/secondary_mirror_segmentation.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_shadow_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_shadow_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/stars.schema.yml +2 -2
- simtools/schemas/model_parameters/store_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/tailcut_scale.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_axis_height.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_random_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_random_error.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_transmission.schema.yml +1 -1
- simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +1 -1
- simtools/schemas/model_parameters/teltrig_min_time.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_jitter.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_current_limit.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_pixels.schema.yml +1 -1
- simtools/schemas/plot_configuration.metaschema.yml +5 -2
- simtools/schemas/production_configuration_metrics.schema.yml +12 -2
- simtools/schemas/production_tables.schema.yml +7 -2
- simtools/simtel/simtel_config_reader.py +2 -2
- simtools/simtel/simtel_config_writer.py +33 -23
- simtools/simtel/simtel_io_event_histograms.py +483 -0
- simtools/simtel/simtel_io_event_reader.py +65 -43
- simtools/simtel/simtel_io_event_writer.py +40 -20
- simtools/simtel/simtel_io_metadata.py +1 -1
- simtools/simtel/simtel_table_reader.py +95 -13
- simtools/simtel/simulator_array.py +138 -10
- simtools/simtel/simulator_camera_efficiency.py +32 -23
- simtools/simtel/simulator_light_emission.py +437 -271
- simtools/simtel/simulator_ray_tracing.py +1 -1
- simtools/simulator.py +105 -147
- simtools/telescope_trigger_rates.py +119 -0
- simtools/testing/configuration.py +24 -26
- simtools/testing/helpers.py +2 -2
- simtools/testing/log_inspector.py +52 -0
- simtools/testing/validate_output.py +87 -37
- simtools/utils/general.py +125 -255
- simtools/utils/geometry.py +56 -0
- simtools/utils/names.py +1 -1
- simtools/visualization/legend_handlers.py +180 -264
- simtools/visualization/plot_array_layout.py +20 -8
- simtools/visualization/plot_incident_angles.py +431 -0
- simtools/visualization/plot_pixels.py +1 -1
- simtools/visualization/plot_simtel_event_histograms.py +376 -0
- simtools/visualization/plot_simtel_events.py +816 -0
- simtools/visualization/plot_tables.py +133 -37
- simtools/visualization/visualize.py +1 -100
- gammasimtools-0.18.0.dist-info/RECORD +0 -376
- simtools/applications/calculate_trigger_rate.py +0 -187
- simtools/applications/generate_sim_telarray_histograms.py +0 -196
- simtools/production_configuration/derive_corsika_limits_grid.py +0 -232
- simtools/simtel/simtel_io_histogram.py +0 -621
- simtools/simtel/simtel_io_histograms.py +0 -552
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/top_level.txt +0 -0
- /simtools/{io_operations → io}/hdf5_handler.py +0 -0
- /simtools/{io_operations → io}/legacy_data_handler.py +0 -0
- /simtools/{io_operations/io_table_handler.py → io/table_handler.py} +0 -0
|
@@ -12,17 +12,16 @@ query point.
|
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
import itertools
|
|
15
|
-
import json
|
|
16
15
|
import logging
|
|
17
16
|
from pathlib import Path
|
|
18
17
|
|
|
19
18
|
import astropy.units as u
|
|
20
19
|
|
|
20
|
+
from simtools.io import ascii_handler
|
|
21
21
|
from simtools.production_configuration.calculate_statistical_uncertainties_grid_point import (
|
|
22
22
|
StatisticalUncertaintyEvaluator,
|
|
23
23
|
)
|
|
24
24
|
from simtools.production_configuration.interpolation_handler import InterpolationHandler
|
|
25
|
-
from simtools.utils.general import collect_data_from_file
|
|
26
25
|
|
|
27
26
|
|
|
28
27
|
class ProductionStatisticsHandler:
|
|
@@ -48,7 +47,7 @@ class ProductionStatisticsHandler:
|
|
|
48
47
|
self.args = args_dict
|
|
49
48
|
self.logger = logging.getLogger(__name__)
|
|
50
49
|
self.output_path = output_path
|
|
51
|
-
self.metrics = collect_data_from_file(self.args["metrics_file"])
|
|
50
|
+
self.metrics = ascii_handler.collect_data_from_file(self.args["metrics_file"])
|
|
52
51
|
self.evaluator_instances = []
|
|
53
52
|
self.interpolation_handler = None
|
|
54
53
|
self.grid_points_production = self._load_grid_points_production()
|
|
@@ -56,7 +55,7 @@ class ProductionStatisticsHandler:
|
|
|
56
55
|
def _load_grid_points_production(self):
|
|
57
56
|
"""Load grid points from the JSON file."""
|
|
58
57
|
grid_points_production_file = self.args["grid_points_production_file"]
|
|
59
|
-
return collect_data_from_file(grid_points_production_file)
|
|
58
|
+
return ascii_handler.collect_data_from_file(grid_points_production_file)
|
|
60
59
|
|
|
61
60
|
def initialize_evaluators(self):
|
|
62
61
|
"""Initialize StatisticalUncertaintyEvaluator instances for the given grid point."""
|
|
@@ -127,8 +126,10 @@ class ProductionStatisticsHandler:
|
|
|
127
126
|
output_filename = self.args["output_file"]
|
|
128
127
|
self.output_path.mkdir(parents=True, exist_ok=True)
|
|
129
128
|
output_file_path = self.output_path.joinpath(output_filename)
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
ascii_handler.write_data_to_file(
|
|
130
|
+
data=output_data,
|
|
131
|
+
output_file=output_file_path,
|
|
132
|
+
)
|
|
132
133
|
self.logger.info(f"Output saved to {self.output_path}")
|
|
133
134
|
|
|
134
135
|
def plot_production_statistics_comparison(self):
|
|
@@ -9,7 +9,6 @@ Additionally, it allows for converting between Altitude/Azimuth and Right Ascens
|
|
|
9
9
|
Declination coordinates. The resulting grid points are saved to a file.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
-
import json
|
|
13
12
|
import logging
|
|
14
13
|
|
|
15
14
|
import numpy as np
|
|
@@ -19,6 +18,8 @@ from astropy.table import Table
|
|
|
19
18
|
from astropy.units import Quantity
|
|
20
19
|
from scipy.interpolate import griddata
|
|
21
20
|
|
|
21
|
+
from simtools.io import ascii_handler
|
|
22
|
+
|
|
22
23
|
|
|
23
24
|
class GridGeneration:
|
|
24
25
|
"""
|
|
@@ -331,7 +332,7 @@ class GridGeneration:
|
|
|
331
332
|
point["dec"] = radec.dec.deg * u.deg
|
|
332
333
|
return grid_points
|
|
333
334
|
|
|
334
|
-
def serialize_grid_points(self, grid_points, output_file
|
|
335
|
+
def serialize_grid_points(self, grid_points, output_file):
|
|
335
336
|
"""Serialize the grid output and save to a file or print to the console."""
|
|
336
337
|
cleaned_points = []
|
|
337
338
|
|
|
@@ -346,15 +347,12 @@ class GridGeneration:
|
|
|
346
347
|
|
|
347
348
|
cleaned_points.append(cleaned_point)
|
|
348
349
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
else:
|
|
356
|
-
self._logger.info(output_data)
|
|
357
|
-
return output_data
|
|
350
|
+
ascii_handler.write_data_to_file(
|
|
351
|
+
data=cleaned_points,
|
|
352
|
+
output_file=output_file,
|
|
353
|
+
sort_keys=False,
|
|
354
|
+
)
|
|
355
|
+
self._logger.info(f"Output saved to {output_file}")
|
|
358
356
|
|
|
359
357
|
def serialize_quantity(self, value):
|
|
360
358
|
"""Serialize Quantity."""
|
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
"""Class for merging CORSIKA limit tables and checking grid completeness."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from itertools import product
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import matplotlib.pyplot as plt
|
|
8
|
+
import numpy as np
|
|
9
|
+
from astropy.table import unique, vstack
|
|
10
|
+
|
|
11
|
+
import simtools.utils.general as gen
|
|
12
|
+
from simtools.data_model import data_reader
|
|
13
|
+
from simtools.data_model.metadata_collector import MetadataCollector
|
|
14
|
+
from simtools.io import io_handler
|
|
15
|
+
|
|
16
|
+
_logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
ZENITH_LABEL = "Zenith [deg]"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class CorsikaMergeLimits:
|
|
22
|
+
"""Class for merging CORSIKA limit tables and checking grid completeness."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, output_dir=None):
|
|
25
|
+
"""Initialize CorsikaMergeLimits.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
output_dir : Path or str, optional
|
|
30
|
+
Output directory path. If None, will use the default from IOHandler.
|
|
31
|
+
"""
|
|
32
|
+
self.output_dir = (
|
|
33
|
+
io_handler.IOHandler().get_output_directory() if output_dir is None else output_dir
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
def read_file_list(self, file_list_path):
|
|
37
|
+
"""Read a list of input files from a text file.
|
|
38
|
+
|
|
39
|
+
The text file should contain one file path per line.
|
|
40
|
+
Lines starting with '#' are treated as comments and ignored.
|
|
41
|
+
Empty lines are also ignored.
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
file_list_path : Path or str
|
|
46
|
+
Path to the text file containing the list of input files.
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
list
|
|
51
|
+
List of Path objects for the input files.
|
|
52
|
+
|
|
53
|
+
Raises
|
|
54
|
+
------
|
|
55
|
+
FileNotFoundError
|
|
56
|
+
If the file list does not exist.
|
|
57
|
+
"""
|
|
58
|
+
file_list_path = Path(file_list_path).expanduser()
|
|
59
|
+
_logger.info(f"Reading input files from list file: {file_list_path}")
|
|
60
|
+
|
|
61
|
+
if not file_list_path.exists():
|
|
62
|
+
raise FileNotFoundError(f"Input files list not found: {file_list_path}")
|
|
63
|
+
|
|
64
|
+
files = []
|
|
65
|
+
with open(file_list_path, encoding="utf-8") as f:
|
|
66
|
+
for line in f:
|
|
67
|
+
line = line.strip()
|
|
68
|
+
if line and not line.startswith("#"): # Skip empty lines and comments
|
|
69
|
+
file_path = Path(line).expanduser()
|
|
70
|
+
files.append(file_path)
|
|
71
|
+
|
|
72
|
+
_logger.info(f"Found {len(files)} files in list file {file_list_path}")
|
|
73
|
+
return files
|
|
74
|
+
|
|
75
|
+
def _read_and_collect_tables(self, input_files):
|
|
76
|
+
"""Read tables from files and collect metadata. Move loss_fraction from meta to column."""
|
|
77
|
+
tables = []
|
|
78
|
+
metadata = {}
|
|
79
|
+
# Track grid points and their associated values to check for inconsistencies
|
|
80
|
+
grid_point_values = {}
|
|
81
|
+
duplicate_points = []
|
|
82
|
+
inconsistent_points = []
|
|
83
|
+
|
|
84
|
+
for file_path in input_files:
|
|
85
|
+
table = data_reader.read_table_from_file(file_path)
|
|
86
|
+
# Move loss_fraction from meta to column
|
|
87
|
+
table["loss_fraction"] = table.meta.pop("loss_fraction")
|
|
88
|
+
tables.append(table)
|
|
89
|
+
|
|
90
|
+
for row in table:
|
|
91
|
+
grid_point = (row["zenith"], row["azimuth"], row["nsb_level"], row["array_name"])
|
|
92
|
+
|
|
93
|
+
if grid_point in grid_point_values:
|
|
94
|
+
duplicate_points.append(grid_point)
|
|
95
|
+
|
|
96
|
+
current_values = {
|
|
97
|
+
col: row[col]
|
|
98
|
+
for col in row.colnames
|
|
99
|
+
if col not in ["zenith", "azimuth", "nsb_level", "array_name"]
|
|
100
|
+
}
|
|
101
|
+
previous_values = grid_point_values[grid_point]
|
|
102
|
+
|
|
103
|
+
keys_to_compare = set(current_values.keys()) & set(previous_values.keys()) - {
|
|
104
|
+
"telescope_ids"
|
|
105
|
+
}
|
|
106
|
+
if any(
|
|
107
|
+
not np.array_equal(current_values[k], previous_values[k])
|
|
108
|
+
for k in keys_to_compare
|
|
109
|
+
):
|
|
110
|
+
inconsistent_points.append(
|
|
111
|
+
{
|
|
112
|
+
"grid_point": grid_point,
|
|
113
|
+
"file": str(file_path),
|
|
114
|
+
"previous_file": grid_point_values[grid_point]["__file__"],
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
grid_point_values[grid_point] = current_values
|
|
119
|
+
grid_point_values[grid_point]["__file__"] = str(file_path)
|
|
120
|
+
else:
|
|
121
|
+
values = {
|
|
122
|
+
col: row[col]
|
|
123
|
+
for col in row.colnames
|
|
124
|
+
if col not in ["zenith", "azimuth", "nsb_level", "array_name"]
|
|
125
|
+
}
|
|
126
|
+
values["__file__"] = str(file_path)
|
|
127
|
+
grid_point_values[grid_point] = values
|
|
128
|
+
|
|
129
|
+
if not metadata:
|
|
130
|
+
metadata = table.meta
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
tables,
|
|
134
|
+
metadata,
|
|
135
|
+
set(grid_point_values.keys()),
|
|
136
|
+
duplicate_points,
|
|
137
|
+
inconsistent_points,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
def _report_and_merge(self, tables, metadata, duplicate_points, inconsistent_points):
|
|
141
|
+
"""Report issues and merge tables.
|
|
142
|
+
|
|
143
|
+
Parameters
|
|
144
|
+
----------
|
|
145
|
+
tables : list
|
|
146
|
+
List of tables to merge.
|
|
147
|
+
metadata : dict
|
|
148
|
+
Metadata to include in the merged table.
|
|
149
|
+
duplicate_points : list
|
|
150
|
+
List of grid points that occur in multiple tables.
|
|
151
|
+
inconsistent_points : list
|
|
152
|
+
List of grid points with inconsistent values across tables.
|
|
153
|
+
|
|
154
|
+
Returns
|
|
155
|
+
-------
|
|
156
|
+
astropy.table.Table
|
|
157
|
+
The merged table.
|
|
158
|
+
|
|
159
|
+
Raises
|
|
160
|
+
------
|
|
161
|
+
ValueError
|
|
162
|
+
If inconsistent duplicate grid points are found.
|
|
163
|
+
"""
|
|
164
|
+
if duplicate_points:
|
|
165
|
+
_logger.warning(f"Found {len(duplicate_points)} duplicate grid points across tables")
|
|
166
|
+
_logger.warning(f"First few duplicates: {duplicate_points[:5]}")
|
|
167
|
+
|
|
168
|
+
if inconsistent_points:
|
|
169
|
+
message = (
|
|
170
|
+
f"Found {len(inconsistent_points)} grid points with inconsistent values in "
|
|
171
|
+
"tables. This likely indicates an issue with the input data. "
|
|
172
|
+
f"First inconsistent point: {inconsistent_points[0]}"
|
|
173
|
+
)
|
|
174
|
+
_logger.error(message)
|
|
175
|
+
raise ValueError(message)
|
|
176
|
+
|
|
177
|
+
_logger.info("All duplicates have consistent values. Last occurrence will be kept.")
|
|
178
|
+
|
|
179
|
+
merged_table = vstack(tables, metadata_conflicts="silent")
|
|
180
|
+
merged_table.meta.update(metadata)
|
|
181
|
+
return merged_table
|
|
182
|
+
|
|
183
|
+
def _remove_duplicates(self, merged_table):
|
|
184
|
+
"""Remove duplicate grid points from the merged table, keeping the last occurrence."""
|
|
185
|
+
keys = ["array_name", "zenith", "azimuth", "nsb_level"]
|
|
186
|
+
|
|
187
|
+
reversed_table = merged_table[::-1]
|
|
188
|
+
unique_table = unique(reversed_table, keys=keys, keep="first")
|
|
189
|
+
|
|
190
|
+
return unique_table[::-1]
|
|
191
|
+
|
|
192
|
+
def merge_tables(self, input_files):
|
|
193
|
+
"""Merge multiple CORSIKA limit tables into a single table.
|
|
194
|
+
|
|
195
|
+
This function reads and merges CORSIKA limit tables from multiple files,
|
|
196
|
+
handling duplicate grid points by checking for consistency and raising an
|
|
197
|
+
error if inconsistent duplicates are found. It also converts the loss_fraction
|
|
198
|
+
value from metadata to a table column and logs a message if multiple
|
|
199
|
+
loss_fraction values are found.
|
|
200
|
+
|
|
201
|
+
Parameters
|
|
202
|
+
----------
|
|
203
|
+
input_files : list of Path or str
|
|
204
|
+
List of paths to CORSIKA limit table files to merge.
|
|
205
|
+
|
|
206
|
+
Returns
|
|
207
|
+
-------
|
|
208
|
+
astropy.table.Table
|
|
209
|
+
The merged table with duplicates removed, containing all rows from input files.
|
|
210
|
+
The table will be sorted by array_name, zenith, azimuth, and nsb_level.
|
|
211
|
+
|
|
212
|
+
Raises
|
|
213
|
+
------
|
|
214
|
+
ValueError
|
|
215
|
+
If inconsistent duplicate grid points are found.
|
|
216
|
+
"""
|
|
217
|
+
_logger.info(f"Merging {len(input_files)} CORSIKA limit tables")
|
|
218
|
+
|
|
219
|
+
tables, metadata, grid_points, duplicate_points, inconsistent_points = (
|
|
220
|
+
self._read_and_collect_tables(input_files)
|
|
221
|
+
)
|
|
222
|
+
merged_table = self._report_and_merge(
|
|
223
|
+
tables, metadata, duplicate_points, inconsistent_points
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
if "loss_fraction" in merged_table.colnames:
|
|
227
|
+
unique_loss_fractions = np.unique(merged_table["loss_fraction"])
|
|
228
|
+
if len(unique_loss_fractions) > 1:
|
|
229
|
+
_logger.info(
|
|
230
|
+
f"Found multiple loss_fraction values in merged table: {unique_loss_fractions}."
|
|
231
|
+
" Make sure this is intended."
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
merged_table.sort(["array_name", "zenith", "azimuth", "nsb_level"])
|
|
235
|
+
|
|
236
|
+
if duplicate_points:
|
|
237
|
+
original_count = len(merged_table)
|
|
238
|
+
merged_table = self._remove_duplicates(merged_table)
|
|
239
|
+
_logger.info(f"Removed {original_count - len(merged_table)} duplicate grid points")
|
|
240
|
+
|
|
241
|
+
_logger.info(
|
|
242
|
+
f"Merged table has {len(merged_table)} rows with {len(grid_points)} unique grid points"
|
|
243
|
+
)
|
|
244
|
+
return merged_table
|
|
245
|
+
|
|
246
|
+
def check_grid_completeness(self, merged_table, grid_definition):
|
|
247
|
+
"""Check if the grid is complete by verifying all expected combinations exist.
|
|
248
|
+
|
|
249
|
+
This function checks whether all combinations of zenith, azimuth, nsb_level, and array_name
|
|
250
|
+
specified in the grid_definition are present in the merged_table.
|
|
251
|
+
|
|
252
|
+
Parameters
|
|
253
|
+
----------
|
|
254
|
+
merged_table : astropy.table.Table
|
|
255
|
+
The merged table containing CORSIKA limit data.
|
|
256
|
+
grid_definition : dict
|
|
257
|
+
Dictionary defining the grid dimensions with keys:
|
|
258
|
+
'zenith': list of zenith angles,
|
|
259
|
+
'azimuth': list of azimuth angles,
|
|
260
|
+
'nsb_level': list of NSB levels,
|
|
261
|
+
'array_name': list of array name
|
|
262
|
+
|
|
263
|
+
Returns
|
|
264
|
+
-------
|
|
265
|
+
tuple
|
|
266
|
+
A tuple containing: is_complete (bool) that is True if all expected combinations
|
|
267
|
+
are found in the table, and info_dict (dict) with detailed information about the
|
|
268
|
+
completeness check including expected points, found points, and missing combinations.
|
|
269
|
+
"""
|
|
270
|
+
if not grid_definition:
|
|
271
|
+
_logger.info("No grid definition provided, skipping completeness check.")
|
|
272
|
+
return True, {}
|
|
273
|
+
|
|
274
|
+
expected_combinations = list(
|
|
275
|
+
product(
|
|
276
|
+
grid_definition.get("zenith", []),
|
|
277
|
+
grid_definition.get("azimuth", []),
|
|
278
|
+
grid_definition.get("nsb_level", []),
|
|
279
|
+
grid_definition.get("array_name", []),
|
|
280
|
+
)
|
|
281
|
+
)
|
|
282
|
+
_logger.info(f"Expected {len(expected_combinations)} grid point combinations")
|
|
283
|
+
|
|
284
|
+
found_combinations_set = set(
|
|
285
|
+
zip(
|
|
286
|
+
np.array(merged_table["zenith"].value, dtype=str),
|
|
287
|
+
np.array(merged_table["azimuth"].value, dtype=str),
|
|
288
|
+
np.array(merged_table["nsb_level"], dtype=str),
|
|
289
|
+
np.array(merged_table["array_name"], dtype=str),
|
|
290
|
+
)
|
|
291
|
+
)
|
|
292
|
+
_logger.info(f"Found {len(found_combinations_set)} unique grid points in merged table")
|
|
293
|
+
|
|
294
|
+
expected_combinations_str = {tuple(map(str, combo)) for combo in expected_combinations}
|
|
295
|
+
|
|
296
|
+
missing_combinations_str = expected_combinations_str - found_combinations_set
|
|
297
|
+
|
|
298
|
+
missing_combinations = [
|
|
299
|
+
combo
|
|
300
|
+
for combo in expected_combinations
|
|
301
|
+
if tuple(map(str, combo)) in missing_combinations_str
|
|
302
|
+
]
|
|
303
|
+
|
|
304
|
+
is_complete = not missing_combinations
|
|
305
|
+
return is_complete, {
|
|
306
|
+
"expected": len(expected_combinations),
|
|
307
|
+
"found": len(found_combinations_set),
|
|
308
|
+
"missing": missing_combinations,
|
|
309
|
+
"found_str": found_combinations_set,
|
|
310
|
+
"expected_str": expected_combinations_str,
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
def _plot_single_grid_coverage(
|
|
314
|
+
self, ax, zeniths, azimuths, nsb, array_name, found_combinations_str
|
|
315
|
+
):
|
|
316
|
+
"""Plot grid coverage for a single NSB and array_name."""
|
|
317
|
+
z_grid = np.zeros((len(zeniths), len(azimuths)))
|
|
318
|
+
for i, zenith in enumerate(zeniths):
|
|
319
|
+
for j, azimuth in enumerate(azimuths):
|
|
320
|
+
point_str = (str(zenith), str(azimuth), str(nsb), str(array_name))
|
|
321
|
+
if point_str in found_combinations_str:
|
|
322
|
+
z_grid[i, j] = 1
|
|
323
|
+
|
|
324
|
+
az_vals = azimuths.value if hasattr(azimuths, "value") else azimuths
|
|
325
|
+
zen_vals = zeniths.value if hasattr(zeniths, "value") else zeniths
|
|
326
|
+
extent = [
|
|
327
|
+
min(az_vals) - 0.5,
|
|
328
|
+
max(az_vals) + 0.5,
|
|
329
|
+
max(zen_vals) + 0.5,
|
|
330
|
+
min(zen_vals) - 0.5,
|
|
331
|
+
]
|
|
332
|
+
colors = ["red", "green"]
|
|
333
|
+
cmap = plt.matplotlib.colors.ListedColormap(colors)
|
|
334
|
+
im = ax.imshow(z_grid, cmap=cmap, vmin=0, vmax=1, extent=extent)
|
|
335
|
+
|
|
336
|
+
cbar = plt.colorbar(
|
|
337
|
+
im,
|
|
338
|
+
ax=ax,
|
|
339
|
+
ticks=[0, 1],
|
|
340
|
+
label="Coverage",
|
|
341
|
+
shrink=0.25,
|
|
342
|
+
pad=0.02,
|
|
343
|
+
)
|
|
344
|
+
cbar.set_ticklabels(["Missing", "Present"])
|
|
345
|
+
ax.set_title(f"Grid Coverage: NSB={nsb}, Array Name={array_name}")
|
|
346
|
+
ax.set_xlabel("Azimuth [deg]")
|
|
347
|
+
ax.set_ylabel(ZENITH_LABEL)
|
|
348
|
+
ax.set_xticks(az_vals)
|
|
349
|
+
ax.set_yticks(zen_vals)
|
|
350
|
+
ax.grid(which="major", linestyle="-", linewidth="0.5", color="black", alpha=0.3)
|
|
351
|
+
|
|
352
|
+
def plot_grid_coverage(self, merged_table, grid_definition):
|
|
353
|
+
"""Generate plots showing grid coverage for each combination of NSB level and array name.
|
|
354
|
+
|
|
355
|
+
Creates a series of heatmap plots showing which grid points (combinations of zenith and
|
|
356
|
+
azimuth angles) are present or missing in the merged table, for each combination of
|
|
357
|
+
NSB level and array name.
|
|
358
|
+
|
|
359
|
+
Parameters
|
|
360
|
+
----------
|
|
361
|
+
merged_table : astropy.table.Table
|
|
362
|
+
The merged table containing CORSIKA limit data.
|
|
363
|
+
grid_definition : dict
|
|
364
|
+
Dictionary defining the grid dimensions with keys:
|
|
365
|
+
'zenith': list of zenith angles,
|
|
366
|
+
'azimuth': list of azimuth angles,
|
|
367
|
+
'nsb_level': list of NSB levels,
|
|
368
|
+
'array_name': list of array names
|
|
369
|
+
|
|
370
|
+
Returns
|
|
371
|
+
-------
|
|
372
|
+
list
|
|
373
|
+
List of Path objects pointing to the saved plot files.
|
|
374
|
+
"""
|
|
375
|
+
if not grid_definition:
|
|
376
|
+
_logger.info("No grid definition provided, skipping grid coverage plots.")
|
|
377
|
+
return []
|
|
378
|
+
|
|
379
|
+
_logger.info("Generating grid coverage plots")
|
|
380
|
+
output_files = []
|
|
381
|
+
|
|
382
|
+
_, completeness_info = self.check_grid_completeness(merged_table, grid_definition)
|
|
383
|
+
found_combinations_str = completeness_info.get("found_str", set())
|
|
384
|
+
|
|
385
|
+
unique_values = {
|
|
386
|
+
"zeniths": np.array(grid_definition.get("zenith", [])),
|
|
387
|
+
"azimuths": np.array(grid_definition.get("azimuth", [])),
|
|
388
|
+
"nsb_levels": np.array(grid_definition.get("nsb_level", [])),
|
|
389
|
+
"array_names": np.array(grid_definition.get("array_name", [])),
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
for nsb, array_name in product(unique_values["nsb_levels"], unique_values["array_names"]):
|
|
393
|
+
_, ax = plt.subplots(figsize=(10, 8))
|
|
394
|
+
self._plot_single_grid_coverage(
|
|
395
|
+
ax,
|
|
396
|
+
unique_values["zeniths"],
|
|
397
|
+
unique_values["azimuths"],
|
|
398
|
+
nsb,
|
|
399
|
+
array_name,
|
|
400
|
+
found_combinations_str,
|
|
401
|
+
)
|
|
402
|
+
output_file = self.output_dir / f"grid_coverage_{nsb}_{array_name}.png"
|
|
403
|
+
plt.tight_layout()
|
|
404
|
+
plt.savefig(output_file, bbox_inches="tight")
|
|
405
|
+
plt.close()
|
|
406
|
+
output_files.append(output_file)
|
|
407
|
+
return output_files
|
|
408
|
+
|
|
409
|
+
def plot_limits(self, merged_table):
|
|
410
|
+
"""Create plots showing the derived limits for each combination of array_name and azimuth.
|
|
411
|
+
|
|
412
|
+
Creates plots showing the lower energy limit, upper radius limit, and viewcone radius
|
|
413
|
+
versus zenith angle for each combination of array_name and azimuth angle. Each plot has
|
|
414
|
+
lines for different NSB levels.
|
|
415
|
+
|
|
416
|
+
Parameters
|
|
417
|
+
----------
|
|
418
|
+
merged_table : astropy.table.Table
|
|
419
|
+
The merged table containing CORSIKA limit data.
|
|
420
|
+
|
|
421
|
+
Returns
|
|
422
|
+
-------
|
|
423
|
+
list
|
|
424
|
+
List of Path objects pointing to the saved plot files.
|
|
425
|
+
"""
|
|
426
|
+
_logger.info("Generating limit plots")
|
|
427
|
+
output_files = []
|
|
428
|
+
|
|
429
|
+
grouped_by_layout_az = merged_table.group_by(["array_name", "azimuth"])
|
|
430
|
+
|
|
431
|
+
for group in grouped_by_layout_az.groups:
|
|
432
|
+
array_name = group["array_name"][0]
|
|
433
|
+
azimuth = group["azimuth"][0]
|
|
434
|
+
azimuth_value = azimuth.value if hasattr(azimuth, "value") else azimuth
|
|
435
|
+
|
|
436
|
+
fig, axes = plt.subplots(1, 3, figsize=(18, 6))
|
|
437
|
+
legend_handles, legend_labels = [], []
|
|
438
|
+
|
|
439
|
+
grouped_by_nsb = group.group_by("nsb_level")
|
|
440
|
+
colors = plt.get_cmap("viridis")(np.linspace(0, 1, len(grouped_by_nsb.groups)))
|
|
441
|
+
|
|
442
|
+
for i, nsb_group in enumerate(grouped_by_nsb.groups):
|
|
443
|
+
nsb_level = nsb_group["nsb_level"][0]
|
|
444
|
+
plot_columns = [
|
|
445
|
+
"zenith",
|
|
446
|
+
"lower_energy_limit",
|
|
447
|
+
"upper_radius_limit",
|
|
448
|
+
"viewcone_radius",
|
|
449
|
+
]
|
|
450
|
+
agg_data = nsb_group[plot_columns].group_by("zenith").groups.aggregate(np.mean)
|
|
451
|
+
agg_data.sort("zenith")
|
|
452
|
+
zeniths = agg_data["zenith"].value
|
|
453
|
+
|
|
454
|
+
(line,) = axes[0].plot(
|
|
455
|
+
zeniths, agg_data["lower_energy_limit"], "o-", color=colors[i]
|
|
456
|
+
)
|
|
457
|
+
axes[1].plot(zeniths, agg_data["upper_radius_limit"], "o-", color=colors[i])
|
|
458
|
+
axes[2].plot(zeniths, agg_data["viewcone_radius"], "o-", color=colors[i])
|
|
459
|
+
legend_handles.append(line)
|
|
460
|
+
legend_labels.append(f"NSB={nsb_level}")
|
|
461
|
+
|
|
462
|
+
axes[0].set_title("Lower Energy Limit vs Zenith")
|
|
463
|
+
axes[0].set_xlabel(ZENITH_LABEL)
|
|
464
|
+
axes[0].set_ylabel("Lower Energy Limit [TeV]")
|
|
465
|
+
axes[0].grid(True)
|
|
466
|
+
axes[1].set_title("Upper Radius Limit vs Zenith")
|
|
467
|
+
axes[1].set_xlabel(ZENITH_LABEL)
|
|
468
|
+
axes[1].set_ylabel("Upper Radius Limit [m]")
|
|
469
|
+
axes[1].grid(True)
|
|
470
|
+
axes[2].set_title("Viewcone Radius vs Zenith")
|
|
471
|
+
axes[2].set_xlabel(ZENITH_LABEL)
|
|
472
|
+
axes[2].set_ylabel("Viewcone Radius [deg]")
|
|
473
|
+
axes[2].grid(True)
|
|
474
|
+
|
|
475
|
+
fig.legend(legend_handles, legend_labels, loc="lower center", ncol=len(legend_labels))
|
|
476
|
+
plt.suptitle(f"CORSIKA Limits: Array Name={array_name}, Azimuth={azimuth_value} deg")
|
|
477
|
+
plt.tight_layout()
|
|
478
|
+
plt.subplots_adjust(bottom=0.15)
|
|
479
|
+
|
|
480
|
+
output_file = self.output_dir / f"limits_{array_name}_azimuth{azimuth_value}.png"
|
|
481
|
+
plt.savefig(output_file)
|
|
482
|
+
plt.close(fig)
|
|
483
|
+
output_files.append(output_file)
|
|
484
|
+
return output_files
|
|
485
|
+
|
|
486
|
+
def write_merged_table(self, merged_table, output_file, input_files, grid_completeness):
|
|
487
|
+
"""Write the merged table to file and save metadata.
|
|
488
|
+
|
|
489
|
+
Writes the merged table to the specified output file in ECSV format and
|
|
490
|
+
saves relevant metadata about the merge process, including input files,
|
|
491
|
+
grid completeness statistics, and row count.
|
|
492
|
+
|
|
493
|
+
Parameters
|
|
494
|
+
----------
|
|
495
|
+
merged_table : astropy.table.Table
|
|
496
|
+
The merged table to write to file.
|
|
497
|
+
output_file : Path or str
|
|
498
|
+
Path where the merged table will be written.
|
|
499
|
+
input_files : list of Path or str
|
|
500
|
+
List of input files used to create the merged table.
|
|
501
|
+
grid_completeness : dict
|
|
502
|
+
Dictionary with grid completeness information from check_grid_completeness.
|
|
503
|
+
|
|
504
|
+
Returns
|
|
505
|
+
-------
|
|
506
|
+
Path or str
|
|
507
|
+
The path to the written file (same as output_file).
|
|
508
|
+
"""
|
|
509
|
+
merged_table.meta.update(
|
|
510
|
+
{
|
|
511
|
+
"created_by": "simtools-production-merge-corsika-limits",
|
|
512
|
+
"creation_date": gen.now_date_time_in_isoformat(),
|
|
513
|
+
"input_files_count": len(input_files),
|
|
514
|
+
}
|
|
515
|
+
)
|
|
516
|
+
merged_table.write(output_file, format="ascii.ecsv", overwrite=True)
|
|
517
|
+
_logger.info(f"Merged table written to {output_file}")
|
|
518
|
+
|
|
519
|
+
metadata = {
|
|
520
|
+
"input_files": [str(f) for f in input_files],
|
|
521
|
+
"grid_completeness": grid_completeness.get("is_complete", False),
|
|
522
|
+
"missing_points": len(grid_completeness.get("missing", [])),
|
|
523
|
+
"total_expected_points": grid_completeness.get("expected", 0),
|
|
524
|
+
"found_points": grid_completeness.get("found", 0),
|
|
525
|
+
"row_count": len(merged_table),
|
|
526
|
+
}
|
|
527
|
+
MetadataCollector.dump(metadata, output_file)
|
|
528
|
+
return output_file
|