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
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Provides functionality to evaluate statistical uncertainties from DL2 MC event files.
|
|
3
|
+
|
|
4
|
+
Classes
|
|
5
|
+
-------
|
|
6
|
+
StatisticalErrorEvaluator
|
|
7
|
+
Handles error calculation for given DL2 MC event files and specified metrics.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import logging
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
from astropy import units as u
|
|
16
|
+
from astropy.io import fits
|
|
17
|
+
|
|
18
|
+
_logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class StatisticalErrorEvaluator:
|
|
22
|
+
"""
|
|
23
|
+
Evaluates statistical uncertainties from a DL2 MC event file.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
file_path : str
|
|
28
|
+
Path to the DL2 MC event file.
|
|
29
|
+
file_type : str
|
|
30
|
+
Type of the file, either 'point-like' or 'cone'.
|
|
31
|
+
metrics : dict, optional
|
|
32
|
+
Dictionary of metrics to evaluate. Default is None.
|
|
33
|
+
grid_point : tuple, optional
|
|
34
|
+
Tuple specifying the grid point (energy, azimuth, zenith, NSB, offset).
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
file_path: str,
|
|
40
|
+
file_type: str,
|
|
41
|
+
metrics: dict[str, float],
|
|
42
|
+
grid_point: tuple[float, float, float, float, float] | None = None,
|
|
43
|
+
):
|
|
44
|
+
"""
|
|
45
|
+
Init the evaluator with a DL2 MC event file, its type, and metrics to calculate.
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
file_path : str
|
|
50
|
+
The path to the DL2 MC event file.
|
|
51
|
+
file_type : str
|
|
52
|
+
The type of the file ('point-like' or 'cone').
|
|
53
|
+
metrics : dict, optional
|
|
54
|
+
Dictionary specifying which metrics to compute and their reference values.
|
|
55
|
+
grid_point : tuple, optional
|
|
56
|
+
Tuple specifying the grid point (energy, azimuth, zenith, NSB, offset).
|
|
57
|
+
"""
|
|
58
|
+
self.file_path = file_path
|
|
59
|
+
self.file_type = file_type
|
|
60
|
+
self.metrics = metrics
|
|
61
|
+
self.grid_point = grid_point
|
|
62
|
+
|
|
63
|
+
self.data = self.load_data_from_file()
|
|
64
|
+
|
|
65
|
+
self.uncertainty_effective_area = None
|
|
66
|
+
self.energy_estimate = None
|
|
67
|
+
self.sigma_energy = None
|
|
68
|
+
self.delta_energy = None
|
|
69
|
+
|
|
70
|
+
self.metric_results = None
|
|
71
|
+
self.energy_threshold = None
|
|
72
|
+
|
|
73
|
+
def load_data_from_file(self):
|
|
74
|
+
"""
|
|
75
|
+
Load data from the DL2 MC event file and return dictionaries with units.
|
|
76
|
+
|
|
77
|
+
Returns
|
|
78
|
+
-------
|
|
79
|
+
dict
|
|
80
|
+
Dictionary containing data from the DL2 MC event file with units.
|
|
81
|
+
"""
|
|
82
|
+
data = {}
|
|
83
|
+
try:
|
|
84
|
+
with fits.open(self.file_path) as hdul:
|
|
85
|
+
events_data = hdul["EVENTS"].data # pylint: disable=E1101
|
|
86
|
+
sim_events_data = hdul["SIMULATED EVENTS"].data # pylint: disable=E1101
|
|
87
|
+
event_units = {}
|
|
88
|
+
for idx, col_name in enumerate(events_data.columns.names, start=1):
|
|
89
|
+
unit_key = f"TUNIT{idx}"
|
|
90
|
+
if unit_key in hdul["EVENTS"].header: # pylint: disable=E1101
|
|
91
|
+
event_units[col_name] = u.Unit(
|
|
92
|
+
hdul["EVENTS"].header[unit_key] # pylint: disable=E1101
|
|
93
|
+
)
|
|
94
|
+
else:
|
|
95
|
+
event_units[col_name] = None
|
|
96
|
+
|
|
97
|
+
sim_units = {}
|
|
98
|
+
for idx, col_name in enumerate(sim_events_data.columns.names, start=1):
|
|
99
|
+
unit_key = f"TUNIT{idx}"
|
|
100
|
+
if unit_key in hdul["SIMULATED EVENTS"].header: # pylint: disable=E1101
|
|
101
|
+
sim_units[col_name] = u.Unit(
|
|
102
|
+
hdul["SIMULATED EVENTS"].header[unit_key] # pylint: disable=E1101
|
|
103
|
+
)
|
|
104
|
+
else:
|
|
105
|
+
sim_units[col_name] = None
|
|
106
|
+
# dl2 files are required to have units for these entries
|
|
107
|
+
event_energies_reco = events_data["ENERGY"] * event_units["ENERGY"]
|
|
108
|
+
|
|
109
|
+
event_energies_mc = events_data["MC_ENERGY"] * event_units["MC_ENERGY"]
|
|
110
|
+
|
|
111
|
+
bin_edges_low = sim_events_data["MC_ENERG_LO"] * sim_units["MC_ENERG_LO"]
|
|
112
|
+
|
|
113
|
+
bin_edges_high = sim_events_data["MC_ENERG_HI"] * sim_units["MC_ENERG_HI"]
|
|
114
|
+
|
|
115
|
+
simulated_event_histogram = sim_events_data["EVENTS"] * u.count
|
|
116
|
+
|
|
117
|
+
viewcone = hdul[3].data["viewcone"][0][1] # pylint: disable=E1101
|
|
118
|
+
core_range = hdul[3].data["core_range"][0][1] # pylint: disable=E1101
|
|
119
|
+
|
|
120
|
+
data = {
|
|
121
|
+
"event_energies_reco": event_energies_reco,
|
|
122
|
+
"event_energies_mc": event_energies_mc,
|
|
123
|
+
"bin_edges_low": bin_edges_low,
|
|
124
|
+
"bin_edges_high": bin_edges_high,
|
|
125
|
+
"simulated_event_histogram": simulated_event_histogram,
|
|
126
|
+
"viewcone": viewcone,
|
|
127
|
+
"core_range": core_range,
|
|
128
|
+
}
|
|
129
|
+
unique_azimuths = np.unique(events_data["PNT_AZ"]) * u.deg
|
|
130
|
+
unique_zeniths = 90 * u.deg - np.unique(events_data["PNT_ALT"]) * u.deg
|
|
131
|
+
if self.grid_point is None:
|
|
132
|
+
_logger.info(f"Unique azimuths: {unique_azimuths}")
|
|
133
|
+
_logger.info(f"Unique zeniths: {unique_zeniths}")
|
|
134
|
+
|
|
135
|
+
if len(unique_azimuths) == 1 and len(unique_zeniths) == 1:
|
|
136
|
+
_logger.info(
|
|
137
|
+
f"Setting initial grid point with azimuth: {unique_azimuths[0]}"
|
|
138
|
+
f" zenith: {unique_zeniths[0]}"
|
|
139
|
+
)
|
|
140
|
+
self.grid_point = (
|
|
141
|
+
1 * u.TeV,
|
|
142
|
+
unique_azimuths[0],
|
|
143
|
+
unique_zeniths[0],
|
|
144
|
+
0,
|
|
145
|
+
0 * u.deg,
|
|
146
|
+
) # Initialize grid point with azimuth and zenith
|
|
147
|
+
else:
|
|
148
|
+
msg = "Multiple unique values found for azimuth or zenith."
|
|
149
|
+
_logger.error(msg)
|
|
150
|
+
raise ValueError(msg)
|
|
151
|
+
else:
|
|
152
|
+
_logger.warning(
|
|
153
|
+
f"Grid point already set to: {self.grid_point}. "
|
|
154
|
+
"Overwriting with new values from file."
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
self.grid_point = (
|
|
158
|
+
1 * u.TeV,
|
|
159
|
+
unique_azimuths[0],
|
|
160
|
+
unique_zeniths[0],
|
|
161
|
+
0,
|
|
162
|
+
0 * u.deg,
|
|
163
|
+
)
|
|
164
|
+
_logger.info(f"New grid point values: {self.grid_point}")
|
|
165
|
+
|
|
166
|
+
except FileNotFoundError as e:
|
|
167
|
+
error_message = f"Error loading file {self.file_path}: {e}"
|
|
168
|
+
_logger.error(error_message)
|
|
169
|
+
raise FileNotFoundError(error_message) from e
|
|
170
|
+
return data
|
|
171
|
+
|
|
172
|
+
def create_bin_edges(self):
|
|
173
|
+
"""
|
|
174
|
+
Create unique energy bin edges.
|
|
175
|
+
|
|
176
|
+
Returns
|
|
177
|
+
-------
|
|
178
|
+
bin_edges : array
|
|
179
|
+
Array of unique energy bin edges.
|
|
180
|
+
"""
|
|
181
|
+
bin_edges_low = self.data["bin_edges_low"]
|
|
182
|
+
bin_edges_high = self.data["bin_edges_high"]
|
|
183
|
+
bin_edges = np.concatenate([bin_edges_low, [bin_edges_high[-1]]])
|
|
184
|
+
return np.unique(bin_edges)
|
|
185
|
+
|
|
186
|
+
def compute_triggered_event_histogram(self, event_energies_reco, bin_edges):
|
|
187
|
+
"""
|
|
188
|
+
Compute histogram for triggered events.
|
|
189
|
+
|
|
190
|
+
Parameters
|
|
191
|
+
----------
|
|
192
|
+
event_energies_reco : array
|
|
193
|
+
Array of reconstructed energy per event.
|
|
194
|
+
bin_edges : array
|
|
195
|
+
Array of energy bin edges.
|
|
196
|
+
|
|
197
|
+
Returns
|
|
198
|
+
-------
|
|
199
|
+
triggered_event_histogram : array
|
|
200
|
+
Histogram of triggered events.
|
|
201
|
+
"""
|
|
202
|
+
event_energies_reco = event_energies_reco.to(bin_edges.unit)
|
|
203
|
+
|
|
204
|
+
triggered_event_histogram, _ = np.histogram(event_energies_reco.value, bins=bin_edges.value)
|
|
205
|
+
return triggered_event_histogram * u.count
|
|
206
|
+
|
|
207
|
+
def compute_efficiency_and_errors(self, triggered_event_counts, simulated_event_counts):
|
|
208
|
+
"""
|
|
209
|
+
Compute trigger efficiency and its statistical error using the binomial distribution.
|
|
210
|
+
|
|
211
|
+
Parameters
|
|
212
|
+
----------
|
|
213
|
+
triggered_event_counts : array with units
|
|
214
|
+
Histogram counts of the triggered events.
|
|
215
|
+
simulated_event_counts : array with units
|
|
216
|
+
Histogram counts of the simulated events.
|
|
217
|
+
|
|
218
|
+
Returns
|
|
219
|
+
-------
|
|
220
|
+
efficiencies : array
|
|
221
|
+
Array of calculated efficiencies.
|
|
222
|
+
relative_errors : array
|
|
223
|
+
Array of relative uncertainties.
|
|
224
|
+
"""
|
|
225
|
+
# Ensure the inputs have compatible units
|
|
226
|
+
triggered_event_counts = triggered_event_counts.to(u.ct)
|
|
227
|
+
simulated_event_counts = simulated_event_counts.to(u.ct)
|
|
228
|
+
|
|
229
|
+
# Compute efficiencies, ensuring the output is dimensionless
|
|
230
|
+
efficiencies = np.divide(
|
|
231
|
+
triggered_event_counts,
|
|
232
|
+
simulated_event_counts,
|
|
233
|
+
out=np.zeros_like(triggered_event_counts),
|
|
234
|
+
where=simulated_event_counts > 0,
|
|
235
|
+
).to(u.dimensionless_unscaled)
|
|
236
|
+
|
|
237
|
+
# Set up a mask for valid data with a unit-consistent threshold
|
|
238
|
+
if np.any(triggered_event_counts > simulated_event_counts):
|
|
239
|
+
raise ValueError(
|
|
240
|
+
"Triggered event counts exceed simulated event counts. Please check input data."
|
|
241
|
+
)
|
|
242
|
+
valid = (simulated_event_counts > 0 * u.ct) & (triggered_event_counts > 0 * u.ct)
|
|
243
|
+
|
|
244
|
+
uncertainties = np.zeros_like(triggered_event_counts.value) * u.dimensionless_unscaled
|
|
245
|
+
|
|
246
|
+
if np.any(valid):
|
|
247
|
+
uncertainties[valid] = np.sqrt(
|
|
248
|
+
np.maximum(
|
|
249
|
+
simulated_event_counts[valid]
|
|
250
|
+
/ triggered_event_counts[valid]
|
|
251
|
+
* (1 - triggered_event_counts[valid] / simulated_event_counts[valid]),
|
|
252
|
+
0,
|
|
253
|
+
)
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
# Compute relative errors
|
|
257
|
+
relative_errors = np.divide(
|
|
258
|
+
uncertainties,
|
|
259
|
+
np.sqrt(simulated_event_counts.value),
|
|
260
|
+
out=np.zeros_like(uncertainties, dtype=float),
|
|
261
|
+
where=uncertainties > 0,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
return efficiencies, relative_errors
|
|
265
|
+
|
|
266
|
+
def calculate_energy_threshold(self, requested_eff_area_fraction=0.1):
|
|
267
|
+
"""
|
|
268
|
+
Calculate the energy threshold where the effective area exceeds 10% of its maximum value.
|
|
269
|
+
|
|
270
|
+
Returns
|
|
271
|
+
-------
|
|
272
|
+
float
|
|
273
|
+
Energy threshold value.
|
|
274
|
+
"""
|
|
275
|
+
bin_edges = self.create_bin_edges()
|
|
276
|
+
triggered_event_histogram = self.compute_triggered_event_histogram(
|
|
277
|
+
self.data["event_energies_mc"], bin_edges
|
|
278
|
+
)
|
|
279
|
+
simulated_event_histogram = self.data["simulated_event_histogram"]
|
|
280
|
+
|
|
281
|
+
efficiencies, _ = self.compute_efficiency_and_errors(
|
|
282
|
+
triggered_event_histogram, simulated_event_histogram
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
# Determine the effective area threshold (10% of max effective area)
|
|
286
|
+
max_efficiency = np.max(efficiencies)
|
|
287
|
+
threshold_efficiency = requested_eff_area_fraction * max_efficiency
|
|
288
|
+
|
|
289
|
+
threshold_index = np.argmax(efficiencies >= threshold_efficiency)
|
|
290
|
+
if threshold_index == 0 and efficiencies[0] < threshold_efficiency:
|
|
291
|
+
return
|
|
292
|
+
|
|
293
|
+
self.energy_threshold = bin_edges[threshold_index]
|
|
294
|
+
|
|
295
|
+
def calculate_uncertainty_effective_area(self):
|
|
296
|
+
"""
|
|
297
|
+
Calculate the uncertainties on the effective collection area.
|
|
298
|
+
|
|
299
|
+
Returns
|
|
300
|
+
-------
|
|
301
|
+
errors : dict
|
|
302
|
+
Dictionary with uncertainties for the file.
|
|
303
|
+
"""
|
|
304
|
+
bin_edges = self.create_bin_edges()
|
|
305
|
+
triggered_event_histogram = self.compute_triggered_event_histogram(
|
|
306
|
+
self.data["event_energies_mc"], bin_edges
|
|
307
|
+
)
|
|
308
|
+
simulated_event_histogram = self.data["simulated_event_histogram"]
|
|
309
|
+
_, relative_errors = self.compute_efficiency_and_errors(
|
|
310
|
+
triggered_event_histogram, simulated_event_histogram
|
|
311
|
+
)
|
|
312
|
+
return {"relative_errors": relative_errors}
|
|
313
|
+
|
|
314
|
+
def calculate_energy_estimate(self):
|
|
315
|
+
"""
|
|
316
|
+
Calculate the uncertainties in energy estimation.
|
|
317
|
+
|
|
318
|
+
Returns
|
|
319
|
+
-------
|
|
320
|
+
float
|
|
321
|
+
The calculated uncertainty for energy estimation.
|
|
322
|
+
"""
|
|
323
|
+
logging.info("Calculating Energy Resolution Error")
|
|
324
|
+
|
|
325
|
+
event_energies_reco = self.data["event_energies_reco"]
|
|
326
|
+
event_energies_mc = self.data["event_energies_mc"]
|
|
327
|
+
|
|
328
|
+
if len(event_energies_reco) != len(event_energies_mc):
|
|
329
|
+
raise ValueError(f"Mismatch in the number of energies for file {self.file_path}")
|
|
330
|
+
|
|
331
|
+
energy_deviation = (event_energies_reco - event_energies_mc) / event_energies_mc
|
|
332
|
+
|
|
333
|
+
bin_edges = self.create_bin_edges()
|
|
334
|
+
bin_indices = np.digitize(event_energies_reco, bin_edges) - 1
|
|
335
|
+
|
|
336
|
+
energy_deviation_by_bin = [
|
|
337
|
+
energy_deviation[bin_indices == i] for i in range(len(bin_edges) - 1)
|
|
338
|
+
]
|
|
339
|
+
|
|
340
|
+
# Calculate sigma for each bin
|
|
341
|
+
sigma_energy = [np.std(d) if len(d) > 0 else np.nan for d in energy_deviation_by_bin]
|
|
342
|
+
|
|
343
|
+
# Calculate delta_energy as the mean deviation for each bin
|
|
344
|
+
delta_energy = [np.mean(d) if len(d) > 0 else np.nan for d in energy_deviation_by_bin]
|
|
345
|
+
|
|
346
|
+
# Combine sigma into a single measure
|
|
347
|
+
overall_uncertainty = np.nanmean(sigma_energy)
|
|
348
|
+
|
|
349
|
+
return overall_uncertainty, sigma_energy, delta_energy
|
|
350
|
+
|
|
351
|
+
def calculate_metrics(self):
|
|
352
|
+
"""Calculate all defined metrics as specified in self.metrics and store results."""
|
|
353
|
+
if "uncertainty_effective_area" in self.metrics:
|
|
354
|
+
|
|
355
|
+
self.uncertainty_effective_area = self.calculate_uncertainty_effective_area()
|
|
356
|
+
if self.uncertainty_effective_area:
|
|
357
|
+
validity_range = self.metrics.get("uncertainty_effective_area", {}).get(
|
|
358
|
+
"valid_range"
|
|
359
|
+
)
|
|
360
|
+
min_energy, max_energy = validity_range["value"][0] * u.Unit(
|
|
361
|
+
validity_range["unit"]
|
|
362
|
+
), validity_range["value"][1] * u.Unit(validity_range["unit"])
|
|
363
|
+
|
|
364
|
+
valid_errors = [
|
|
365
|
+
error
|
|
366
|
+
for energy, error in zip(
|
|
367
|
+
self.data["bin_edges_low"],
|
|
368
|
+
self.uncertainty_effective_area["relative_errors"],
|
|
369
|
+
)
|
|
370
|
+
if min_energy <= energy <= max_energy
|
|
371
|
+
]
|
|
372
|
+
self.uncertainty_effective_area["max_error"] = (
|
|
373
|
+
max(valid_errors) if valid_errors else 0.0
|
|
374
|
+
)
|
|
375
|
+
ref_value = self.metrics.get("uncertainty_effective_area", {}).get("target_error")[
|
|
376
|
+
"value"
|
|
377
|
+
]
|
|
378
|
+
_logger.info(
|
|
379
|
+
f"Effective Area Error (max in validity range): "
|
|
380
|
+
f"{self.uncertainty_effective_area['max_error'].value:.6f}, "
|
|
381
|
+
f"Reference: {ref_value:.3f}"
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
if "energy_estimate" in self.metrics:
|
|
385
|
+
self.energy_estimate, self.sigma_energy, self.delta_energy = (
|
|
386
|
+
self.calculate_energy_estimate()
|
|
387
|
+
)
|
|
388
|
+
ref_value = self.metrics.get("energy_estimate", {}).get("target_error")["value"]
|
|
389
|
+
_logger.info(
|
|
390
|
+
f"Energy Estimate Error: {self.energy_estimate:.3f}, Reference: {ref_value:.3f}"
|
|
391
|
+
)
|
|
392
|
+
else:
|
|
393
|
+
raise ValueError("Invalid metric specified.")
|
|
394
|
+
self.metric_results = {
|
|
395
|
+
"uncertainty_effective_area": self.uncertainty_effective_area,
|
|
396
|
+
"energy_estimate": self.energy_estimate,
|
|
397
|
+
}
|
|
398
|
+
return self.metric_results
|
|
399
|
+
|
|
400
|
+
def calculate_max_error_for_effective_area(self):
|
|
401
|
+
"""
|
|
402
|
+
Calculate the maximum relative error for effective area.
|
|
403
|
+
|
|
404
|
+
Returns
|
|
405
|
+
-------
|
|
406
|
+
max_error : float
|
|
407
|
+
Maximum relative error.
|
|
408
|
+
"""
|
|
409
|
+
if "relative_errors" in self.metric_results["uncertainty_effective_area"]:
|
|
410
|
+
return np.max(self.metric_results["uncertainty_effective_area"]["relative_errors"])
|
|
411
|
+
if self.uncertainty_effective_area:
|
|
412
|
+
return np.max(self.uncertainty_effective_area["relative_errors"])
|
|
413
|
+
return None
|
|
414
|
+
|
|
415
|
+
def calculate_overall_metric(self, metric="average"):
|
|
416
|
+
"""
|
|
417
|
+
Calculate an overall metric for the statistical uncertainties.
|
|
418
|
+
|
|
419
|
+
Parameters
|
|
420
|
+
----------
|
|
421
|
+
metric : str
|
|
422
|
+
The metric to calculate ('average', 'maximum').
|
|
423
|
+
|
|
424
|
+
Returns
|
|
425
|
+
-------
|
|
426
|
+
dict
|
|
427
|
+
Dictionary with overall maximum errors for each metric.
|
|
428
|
+
"""
|
|
429
|
+
# Decide how to combine the metrics
|
|
430
|
+
if self.metric_results is None:
|
|
431
|
+
raise ValueError("Metrics have not been computed yet.")
|
|
432
|
+
|
|
433
|
+
overall_max_errors = {}
|
|
434
|
+
|
|
435
|
+
for metric_name, result in self.metric_results.items():
|
|
436
|
+
if metric_name == "uncertainty_effective_area":
|
|
437
|
+
max_errors = self.calculate_max_error_for_effective_area()
|
|
438
|
+
overall_max_errors[metric_name] = max_errors if max_errors else 0
|
|
439
|
+
elif metric_name in [
|
|
440
|
+
"error_gamma_ray_psf",
|
|
441
|
+
]:
|
|
442
|
+
overall_max_errors[metric_name] = result
|
|
443
|
+
else:
|
|
444
|
+
raise ValueError(f"Unsupported result type for {metric_name}: {type(result)}")
|
|
445
|
+
_logger.info(f"overall_max_errors {overall_max_errors}")
|
|
446
|
+
all_max_errors = list(overall_max_errors.values())
|
|
447
|
+
if metric == "average":
|
|
448
|
+
overall_metric = np.mean(all_max_errors)
|
|
449
|
+
elif metric == "maximum":
|
|
450
|
+
overall_metric = np.max(all_max_errors)
|
|
451
|
+
else:
|
|
452
|
+
raise ValueError(f"Unsupported metric: {metric}")
|
|
453
|
+
|
|
454
|
+
return overall_metric
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Calculate the scaled number of events based on metrics.
|
|
3
|
+
|
|
4
|
+
Module for scaling events based on statistical error metrics. Contains the `EventScaler` class,
|
|
5
|
+
which scales the number of events for both the entire dataset and specific grid points.
|
|
6
|
+
Scaling factors are calculated using error metrics and the evaluator's results.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
import astropy.units as u
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
from simtools.production_configuration.calculate_statistical_errors_grid_point import (
|
|
15
|
+
StatisticalErrorEvaluator,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
_logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class EventScaler:
|
|
22
|
+
"""
|
|
23
|
+
Scales the number of events based on statistical error metrics.
|
|
24
|
+
|
|
25
|
+
Supports scaling both the entire dataset and specific grid points like energy values.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, evaluator: StatisticalErrorEvaluator, science_case: str, metrics: dict):
|
|
29
|
+
"""
|
|
30
|
+
Initialize the EventScaler with the evaluator, science case, and metrics.
|
|
31
|
+
|
|
32
|
+
Parameters
|
|
33
|
+
----------
|
|
34
|
+
evaluator : StatisticalErrorEvaluator
|
|
35
|
+
The evaluator responsible for calculating metrics and handling event data.
|
|
36
|
+
science_case : str
|
|
37
|
+
The science case used to adjust the uncertainty factor.
|
|
38
|
+
metrics : dict
|
|
39
|
+
Dictionary containing metrics, including target error for effective area.
|
|
40
|
+
"""
|
|
41
|
+
self.evaluator = evaluator
|
|
42
|
+
self.science_case = science_case
|
|
43
|
+
self.metrics = metrics
|
|
44
|
+
|
|
45
|
+
def scale_events(self, return_sum: bool = True) -> u.Quantity:
|
|
46
|
+
"""
|
|
47
|
+
Calculate the scaled number of events based on statistical error metrics.
|
|
48
|
+
|
|
49
|
+
If `return_sum` is `True`, the method returns the sum of scaled events for the entire
|
|
50
|
+
dataset. If `return_sum` is `False`, it returns the scaled number of events for each
|
|
51
|
+
grid point (e.g., along the energy axis).
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
----------
|
|
55
|
+
return_sum : bool, optional
|
|
56
|
+
If `True`, returns the sum of scaled events for the entire dataset. If `False`,
|
|
57
|
+
returns the scaled events for each grid point along the energy axis. Default is `True`.
|
|
58
|
+
|
|
59
|
+
Returns
|
|
60
|
+
-------
|
|
61
|
+
u.Quantity
|
|
62
|
+
If `return_sum` is `True`, returns the total scaled number of events as a `u.Quantity`.
|
|
63
|
+
If `return_sum` is `False`, returns an array of scaled events along the energy axis as
|
|
64
|
+
a `u.Quantity`.
|
|
65
|
+
"""
|
|
66
|
+
scaling_factor = self._compute_scaling_factor()
|
|
67
|
+
|
|
68
|
+
base_events = self._number_of_simulated_events()
|
|
69
|
+
|
|
70
|
+
if return_sum:
|
|
71
|
+
return np.sum(base_events * scaling_factor)
|
|
72
|
+
return base_events * scaling_factor
|
|
73
|
+
|
|
74
|
+
def _compute_scaling_factor(self) -> float:
|
|
75
|
+
"""
|
|
76
|
+
Compute the scaling factor based on the error metrics.
|
|
77
|
+
|
|
78
|
+
Returns
|
|
79
|
+
-------
|
|
80
|
+
float
|
|
81
|
+
The scaling factor.
|
|
82
|
+
"""
|
|
83
|
+
metric_results = self.evaluator.calculate_metrics()
|
|
84
|
+
uncertainty_effective_area = metric_results.get("uncertainty_effective_area", {})
|
|
85
|
+
current_max_error = uncertainty_effective_area.get("max_error")
|
|
86
|
+
target_max_error = self.metrics.get("uncertainty_effective_area", {}).get("target_error")[
|
|
87
|
+
"value"
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
current_max_error / target_max_error
|
|
92
|
+
) ** 2 * self._apply_science_case_scaling_factor()
|
|
93
|
+
|
|
94
|
+
def _apply_science_case_scaling_factor(self) -> float:
|
|
95
|
+
"""
|
|
96
|
+
Apply the uncertainty factor based on the science case.
|
|
97
|
+
|
|
98
|
+
Returns
|
|
99
|
+
-------
|
|
100
|
+
float
|
|
101
|
+
The final scaling factor after applying uncertainty.
|
|
102
|
+
"""
|
|
103
|
+
return 1 if self.science_case == "science case 1" else 1.0
|
|
104
|
+
|
|
105
|
+
def _number_of_simulated_events(self) -> u.Quantity:
|
|
106
|
+
"""
|
|
107
|
+
Fetch the number of simulated events from the evaluator's data.
|
|
108
|
+
|
|
109
|
+
Returns
|
|
110
|
+
-------
|
|
111
|
+
u.Quantity
|
|
112
|
+
The number of simulated events.
|
|
113
|
+
"""
|
|
114
|
+
return self.evaluator.data.get("simulated_event_histogram")
|
|
115
|
+
|
|
116
|
+
def calculate_scaled_events_at_grid_point(
|
|
117
|
+
self,
|
|
118
|
+
grid_point: tuple,
|
|
119
|
+
) -> u.Quantity:
|
|
120
|
+
"""
|
|
121
|
+
Calculate the scaled number of events for a specific energy grid point.
|
|
122
|
+
|
|
123
|
+
Parameters
|
|
124
|
+
----------
|
|
125
|
+
grid_point : tuple
|
|
126
|
+
The grid point specifying energy, azimuth, zenith, NSB, and offset.
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
float
|
|
131
|
+
The scaled number of events at the specified grid point (energy).
|
|
132
|
+
"""
|
|
133
|
+
energy = grid_point[0]
|
|
134
|
+
bin_edges = self.evaluator.create_bin_edges()
|
|
135
|
+
bin_idx = np.digitize(energy, bin_edges) - 1
|
|
136
|
+
|
|
137
|
+
scaling_factor = self._compute_scaling_factor()
|
|
138
|
+
|
|
139
|
+
simulated_event_histogram = self.evaluator.data.get("simulated_event_histogram", [])
|
|
140
|
+
|
|
141
|
+
if bin_idx < 0 or bin_idx >= len(simulated_event_histogram):
|
|
142
|
+
raise ValueError(f"Energy {energy} is outside the range of the simulated events data.")
|
|
143
|
+
|
|
144
|
+
base_events = self._number_of_simulated_events()
|
|
145
|
+
base_event_at_energy = base_events[bin_idx]
|
|
146
|
+
return base_event_at_energy * scaling_factor
|