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,193 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Configures and generates simulation parameters for a specific grid point.
|
|
3
|
+
|
|
4
|
+
Used to configure and generate simulation parameters for a specific grid point
|
|
5
|
+
based on statistical uncertainties.
|
|
6
|
+
The class considers parameters, such as azimuth, elevation, and night sky background,
|
|
7
|
+
to compute core scatter area, viewcone, and the required number of simulated events.
|
|
8
|
+
|
|
9
|
+
Key Components:
|
|
10
|
+
---------------
|
|
11
|
+
- `SimulationConfig`: Main class to handle simulation configuration for a grid point.
|
|
12
|
+
- Attributes:
|
|
13
|
+
- `grid_point` (dict): Contains azimuth, elevation, and night sky background.
|
|
14
|
+
- `ctao_data_level` (str): The data level for the simulation (e.g., 'A', 'B', 'C').
|
|
15
|
+
- `science_case` (str): The science case for the simulation.
|
|
16
|
+
- `file_path` (str): Path to the DL2 MC event file
|
|
17
|
+
used for statistical error evaluation.
|
|
18
|
+
- `file_type` (str): Type of the DL2 MC event file ('point-like' or 'cone').
|
|
19
|
+
- `metrics` (dict, optional): Dictionary of metrics to evaluate.
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import logging
|
|
24
|
+
|
|
25
|
+
from simtools.production_configuration.calculate_statistical_errors_grid_point import (
|
|
26
|
+
StatisticalErrorEvaluator,
|
|
27
|
+
)
|
|
28
|
+
from simtools.production_configuration.event_scaler import EventScaler
|
|
29
|
+
|
|
30
|
+
_logger = logging.getLogger(__name__)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class SimulationConfig:
|
|
34
|
+
"""
|
|
35
|
+
Configures simulation parameters for a specific grid point.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
grid_point : dict
|
|
40
|
+
Dictionary representing a grid point with azimuth, elevation, and night sky background.
|
|
41
|
+
ctao_data_level : str
|
|
42
|
+
The data level (e.g., 'A', 'B', 'C') for the simulation configuration.
|
|
43
|
+
science_case : str
|
|
44
|
+
The science case for the simulation configuration.
|
|
45
|
+
file_path : str
|
|
46
|
+
Path to the DL2 MC event file for statistical uncertainty evaluation.
|
|
47
|
+
file_type : str
|
|
48
|
+
Type of the DL2 MC event file ('point-like' or 'cone').
|
|
49
|
+
metrics : dict, optional
|
|
50
|
+
Dictionary of metrics to evaluate.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(
|
|
54
|
+
self,
|
|
55
|
+
grid_point: dict[str, float],
|
|
56
|
+
ctao_data_level: str,
|
|
57
|
+
science_case: str,
|
|
58
|
+
file_path: str,
|
|
59
|
+
file_type: str,
|
|
60
|
+
metrics: dict[str, float] | None = None,
|
|
61
|
+
):
|
|
62
|
+
"""Initialize the simulation configuration for a grid point."""
|
|
63
|
+
self.grid_point = grid_point
|
|
64
|
+
self.ctao_data_level = ctao_data_level
|
|
65
|
+
self.science_case = science_case
|
|
66
|
+
self.file_path = file_path
|
|
67
|
+
self.file_type = file_type
|
|
68
|
+
self.metrics = metrics or {}
|
|
69
|
+
self.evaluator = StatisticalErrorEvaluator(file_path, file_type, metrics)
|
|
70
|
+
self.event_scaler = EventScaler(self.evaluator, science_case, self.metrics)
|
|
71
|
+
self.simulation_params = {}
|
|
72
|
+
|
|
73
|
+
def configure_simulation(self) -> dict[str, float]:
|
|
74
|
+
"""
|
|
75
|
+
Configure the simulation parameters for the grid point, data level, and science case.
|
|
76
|
+
|
|
77
|
+
Returns
|
|
78
|
+
-------
|
|
79
|
+
dict
|
|
80
|
+
A dictionary with simulation parameters such as core scatter area,
|
|
81
|
+
viewcone, and number of simulated events.
|
|
82
|
+
"""
|
|
83
|
+
core_scatter_area = self._calculate_core_scatter_area()
|
|
84
|
+
viewcone = self._calculate_viewcone()
|
|
85
|
+
number_of_events = self.calculate_required_events()
|
|
86
|
+
|
|
87
|
+
self.simulation_params = {
|
|
88
|
+
"core_scatter_area": core_scatter_area,
|
|
89
|
+
"viewcone": viewcone,
|
|
90
|
+
"number_of_events": number_of_events,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return self.simulation_params
|
|
94
|
+
|
|
95
|
+
def calculate_required_events(self) -> int:
|
|
96
|
+
"""
|
|
97
|
+
Calculate the required number of simulated events based on statistical error metrics.
|
|
98
|
+
|
|
99
|
+
Uses the EventScaler to scale the events.
|
|
100
|
+
|
|
101
|
+
Returns
|
|
102
|
+
-------
|
|
103
|
+
int
|
|
104
|
+
The number of simulated events required.
|
|
105
|
+
"""
|
|
106
|
+
return self.event_scaler.scale_events()
|
|
107
|
+
|
|
108
|
+
def _calculate_core_scatter_area(self) -> float:
|
|
109
|
+
"""
|
|
110
|
+
Calculate the core scatter area based on the grid point and data level.
|
|
111
|
+
|
|
112
|
+
Returns
|
|
113
|
+
-------
|
|
114
|
+
float
|
|
115
|
+
The core scatter area.
|
|
116
|
+
"""
|
|
117
|
+
base_area = self._fetch_simulated_core_scatter_area()
|
|
118
|
+
area_factor = self._get_area_factor_from_grid_point()
|
|
119
|
+
return base_area * area_factor
|
|
120
|
+
|
|
121
|
+
def _calculate_viewcone(self) -> float:
|
|
122
|
+
"""
|
|
123
|
+
Calculate the viewcone based on the grid point conditions and data level.
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
float
|
|
128
|
+
The viewcone value.
|
|
129
|
+
"""
|
|
130
|
+
base_viewcone = self._fetch_simulated_viewcone()
|
|
131
|
+
viewcone_factor = self._get_viewcone_factor_from_grid_point()
|
|
132
|
+
|
|
133
|
+
return base_viewcone * viewcone_factor
|
|
134
|
+
|
|
135
|
+
def _get_area_factor_from_grid_point(self) -> float:
|
|
136
|
+
"""
|
|
137
|
+
Determine the area factor.
|
|
138
|
+
|
|
139
|
+
The area factor is based on the grid point's azimuth,
|
|
140
|
+
elevation, and night sky background.
|
|
141
|
+
|
|
142
|
+
Returns
|
|
143
|
+
-------
|
|
144
|
+
float
|
|
145
|
+
The area factor.
|
|
146
|
+
"""
|
|
147
|
+
azimuth = self.grid_point.get("azimuth", 0)
|
|
148
|
+
elevation = self.grid_point.get("elevation", 0)
|
|
149
|
+
night_sky_background = self.grid_point.get("night_sky_background", 0)
|
|
150
|
+
|
|
151
|
+
# Implement reading of factor from LUT
|
|
152
|
+
return azimuth + elevation + night_sky_background
|
|
153
|
+
|
|
154
|
+
def _get_viewcone_factor_from_grid_point(self) -> float:
|
|
155
|
+
"""
|
|
156
|
+
Determine the viewcone factor.
|
|
157
|
+
|
|
158
|
+
The factor is based on the grid point's azimuth,
|
|
159
|
+
elevation, and night sky background.
|
|
160
|
+
|
|
161
|
+
Returns
|
|
162
|
+
-------
|
|
163
|
+
float
|
|
164
|
+
The viewcone factor.
|
|
165
|
+
"""
|
|
166
|
+
azimuth = self.grid_point.get("azimuth", 0)
|
|
167
|
+
elevation = self.grid_point.get("elevation", 0)
|
|
168
|
+
night_sky_background = self.grid_point.get("night_sky_background", 0)
|
|
169
|
+
|
|
170
|
+
# Implement reading of factor from LUT
|
|
171
|
+
return azimuth + elevation + night_sky_background
|
|
172
|
+
|
|
173
|
+
def _fetch_simulated_core_scatter_area(self) -> float:
|
|
174
|
+
"""
|
|
175
|
+
Fetch the core scatter area from existing simulated files based on grid point conditions.
|
|
176
|
+
|
|
177
|
+
Returns
|
|
178
|
+
-------
|
|
179
|
+
float
|
|
180
|
+
The fetched core scatter outer bound.
|
|
181
|
+
"""
|
|
182
|
+
return self.evaluator.data["core_range"]
|
|
183
|
+
|
|
184
|
+
def _fetch_simulated_viewcone(self) -> float:
|
|
185
|
+
"""
|
|
186
|
+
Fetch the viewcone from existing simulated files based on grid point conditions.
|
|
187
|
+
|
|
188
|
+
Returns
|
|
189
|
+
-------
|
|
190
|
+
float
|
|
191
|
+
The fetched viewcone outer bound.
|
|
192
|
+
"""
|
|
193
|
+
return self.evaluator.data["viewcone"]
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"""Interpolates between instances of StatisticalErrorEvaluator using EventScaler."""
|
|
2
|
+
|
|
3
|
+
import astropy.units as u
|
|
4
|
+
import numpy as np
|
|
5
|
+
from scipy.interpolate import griddata
|
|
6
|
+
|
|
7
|
+
from simtools.production_configuration.calculate_statistical_errors_grid_point import (
|
|
8
|
+
StatisticalErrorEvaluator,
|
|
9
|
+
)
|
|
10
|
+
from simtools.production_configuration.event_scaler import EventScaler
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class InterpolationHandler:
|
|
14
|
+
"""Handle interpolation between multiple StatisticalErrorEvaluator instances."""
|
|
15
|
+
|
|
16
|
+
def __init__(
|
|
17
|
+
self, evaluators: list["StatisticalErrorEvaluator"], science_case: str, metrics: dict
|
|
18
|
+
):
|
|
19
|
+
self.evaluators = evaluators
|
|
20
|
+
self.science_case = science_case
|
|
21
|
+
self.metrics = metrics
|
|
22
|
+
self.event_scalers = [
|
|
23
|
+
EventScaler(e, self.science_case, self.metrics) for e in self.evaluators
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
self.azimuths = [e.grid_point[1].to(u.deg).value for e in self.evaluators]
|
|
27
|
+
self.zeniths = [e.grid_point[2].to(u.deg).value for e in self.evaluators]
|
|
28
|
+
self.nsbs = [e.grid_point[3] for e in self.evaluators]
|
|
29
|
+
self.offsets = [e.grid_point[4].to(u.deg).value for e in self.evaluators]
|
|
30
|
+
|
|
31
|
+
self.energy_grids = [
|
|
32
|
+
(e.data["bin_edges_low"][:-1] + e.data["bin_edges_high"][:-1]) / 2
|
|
33
|
+
for e in self.evaluators
|
|
34
|
+
]
|
|
35
|
+
self.scaled_events = [
|
|
36
|
+
scaler.scale_events(return_sum=False) for scaler in self.event_scalers
|
|
37
|
+
]
|
|
38
|
+
self.energy_thresholds = np.array([e.energy_threshold for e in self.evaluators])
|
|
39
|
+
|
|
40
|
+
self.data, self.grid_points = self._build_data_array()
|
|
41
|
+
|
|
42
|
+
def _build_data_array(self):
|
|
43
|
+
"""
|
|
44
|
+
Build a data array with interpolated values across all dimensions including energy.
|
|
45
|
+
|
|
46
|
+
Returns
|
|
47
|
+
-------
|
|
48
|
+
np.ndarray
|
|
49
|
+
The data array with interpolated values.
|
|
50
|
+
np.ndarray
|
|
51
|
+
The corresponding grid points.
|
|
52
|
+
"""
|
|
53
|
+
# Flatten the energy grid and other dimensions into a combined array
|
|
54
|
+
flat_data_list = []
|
|
55
|
+
flat_grid_points = []
|
|
56
|
+
|
|
57
|
+
for e, energy_grid, scaled_events in zip(
|
|
58
|
+
self.evaluators, self.energy_grids, self.scaled_events
|
|
59
|
+
):
|
|
60
|
+
az = np.full(len(energy_grid), e.grid_point[1].to(u.deg).value)
|
|
61
|
+
zen = np.full(len(energy_grid), e.grid_point[2].to(u.deg).value)
|
|
62
|
+
nsb = np.full(len(energy_grid), e.grid_point[3])
|
|
63
|
+
offset = np.full(len(energy_grid), e.grid_point[4].to(u.deg).value)
|
|
64
|
+
|
|
65
|
+
# Combine grid points and data
|
|
66
|
+
grid_points = np.column_stack([energy_grid.to(u.TeV).value, az, zen, nsb, offset])
|
|
67
|
+
flat_grid_points.append(grid_points)
|
|
68
|
+
flat_data_list.append(scaled_events)
|
|
69
|
+
|
|
70
|
+
# Flatten the list and convert to numpy arrays
|
|
71
|
+
flat_grid_points = np.vstack(flat_grid_points)
|
|
72
|
+
flat_data = np.hstack(flat_data_list)
|
|
73
|
+
|
|
74
|
+
# Sort the grid points and corresponding data by energy
|
|
75
|
+
sorted_indices = np.argsort(flat_grid_points[:, 0])
|
|
76
|
+
sorted_grid_points = flat_grid_points[sorted_indices]
|
|
77
|
+
sorted_data = flat_data[sorted_indices]
|
|
78
|
+
|
|
79
|
+
return sorted_data, sorted_grid_points
|
|
80
|
+
|
|
81
|
+
def _remove_flat_dimensions(self, grid_points):
|
|
82
|
+
"""Identify and remove flat dimensions (dimensions with no variance)."""
|
|
83
|
+
variance = np.var(grid_points, axis=0)
|
|
84
|
+
non_flat_mask = variance > 1e-6 # Threshold for determining flatness
|
|
85
|
+
reduced_grid_points = grid_points[:, non_flat_mask]
|
|
86
|
+
return reduced_grid_points, non_flat_mask
|
|
87
|
+
|
|
88
|
+
def interpolate(self, query_points: np.ndarray) -> np.ndarray:
|
|
89
|
+
"""
|
|
90
|
+
Interpolate the number of simulated events given query points.
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
query_points : np.ndarray
|
|
95
|
+
Array of query points with shape (n, 5), where n is the number of points,
|
|
96
|
+
and 5 represents (energy, azimuth, zenith, nsb, offset).
|
|
97
|
+
|
|
98
|
+
Returns
|
|
99
|
+
-------
|
|
100
|
+
np.ndarray
|
|
101
|
+
Interpolated values at the query points.
|
|
102
|
+
"""
|
|
103
|
+
reduced_grid_points, non_flat_mask = self._remove_flat_dimensions(self.grid_points)
|
|
104
|
+
reduced_query_points = query_points[:, non_flat_mask]
|
|
105
|
+
|
|
106
|
+
# Interpolate using the reduced dimensions
|
|
107
|
+
return griddata(
|
|
108
|
+
reduced_grid_points,
|
|
109
|
+
self.data,
|
|
110
|
+
reduced_query_points,
|
|
111
|
+
method="linear",
|
|
112
|
+
fill_value=np.nan,
|
|
113
|
+
rescale=True,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
def interpolate_energy_threshold(self, query_point: np.ndarray) -> float:
|
|
117
|
+
"""
|
|
118
|
+
Interpolate the energy threshold for a given grid point.
|
|
119
|
+
|
|
120
|
+
Parameters
|
|
121
|
+
----------
|
|
122
|
+
query_point : np.ndarray
|
|
123
|
+
Array specifying the grid point (energy, azimuth, zenith, NSB, offset).
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
float
|
|
128
|
+
Interpolated energy threshold.
|
|
129
|
+
"""
|
|
130
|
+
flat_grid_points = []
|
|
131
|
+
flat_energy_thresholds = []
|
|
132
|
+
|
|
133
|
+
for e in self.evaluators:
|
|
134
|
+
az = e.grid_point[1].to(u.deg).value
|
|
135
|
+
zen = e.grid_point[2].to(u.deg).value
|
|
136
|
+
nsb = e.grid_point[3]
|
|
137
|
+
offset = e.grid_point[4].to(u.deg).value
|
|
138
|
+
grid_point = np.array([az, zen, nsb, offset])
|
|
139
|
+
flat_grid_points.append(grid_point)
|
|
140
|
+
flat_energy_thresholds.append(e.energy_threshold)
|
|
141
|
+
|
|
142
|
+
flat_grid_points = np.array(flat_grid_points)
|
|
143
|
+
flat_energy_thresholds = np.array(flat_energy_thresholds)
|
|
144
|
+
|
|
145
|
+
reduced_grid_points, non_flat_mask = self._remove_flat_dimensions(flat_grid_points)
|
|
146
|
+
full_non_flat_mask = np.concatenate(([False], non_flat_mask))
|
|
147
|
+
reduced_query_point = query_point[0][full_non_flat_mask]
|
|
148
|
+
|
|
149
|
+
interpolated_threshold = griddata(
|
|
150
|
+
reduced_grid_points,
|
|
151
|
+
flat_energy_thresholds,
|
|
152
|
+
reduced_query_point,
|
|
153
|
+
method="linear",
|
|
154
|
+
fill_value=np.nan,
|
|
155
|
+
rescale=False,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
return interpolated_threshold.item()
|
|
159
|
+
|
|
160
|
+
def plot_comparison(self, evaluator: "StatisticalErrorEvaluator"):
|
|
161
|
+
"""
|
|
162
|
+
Plot a comparison between the simulated, scaled, and triggered events.
|
|
163
|
+
|
|
164
|
+
Parameters
|
|
165
|
+
----------
|
|
166
|
+
evaluator : StatisticalErrorEvaluator
|
|
167
|
+
The evaluator for which to plot the comparison.
|
|
168
|
+
"""
|
|
169
|
+
import matplotlib.pyplot as plt # pylint: disable=import-outside-toplevel
|
|
170
|
+
|
|
171
|
+
midpoints = 0.5 * (evaluator.data["bin_edges_high"] + evaluator.data["bin_edges_low"])
|
|
172
|
+
|
|
173
|
+
self.grid_points = np.column_stack(
|
|
174
|
+
[
|
|
175
|
+
midpoints,
|
|
176
|
+
np.full_like(midpoints, evaluator.grid_point[1]),
|
|
177
|
+
np.full_like(midpoints, evaluator.grid_point[2]),
|
|
178
|
+
np.full_like(midpoints, evaluator.grid_point[3]),
|
|
179
|
+
np.full_like(midpoints, evaluator.grid_point[4]),
|
|
180
|
+
]
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
self.interpolate(self.grid_points)
|
|
184
|
+
|
|
185
|
+
plt.plot(midpoints, evaluator.scaled_events, label="Scaled")
|
|
186
|
+
|
|
187
|
+
triggered_event_histogram, _ = np.histogram(
|
|
188
|
+
evaluator.data["event_energies_reco"], bins=evaluator.data["bin_edges_low"]
|
|
189
|
+
)
|
|
190
|
+
plt.plot(midpoints[:-1], triggered_event_histogram, label="Triggered")
|
|
191
|
+
|
|
192
|
+
plt.legend()
|
|
193
|
+
plt.xscale("log")
|
|
194
|
+
plt.xlabel("Energy (Midpoint of Bin Edges)")
|
|
195
|
+
plt.ylabel("Event Count")
|
|
196
|
+
plt.title("Comparison of Simulated, Scaled, and Triggered Events")
|
|
197
|
+
plt.show()
|
|
File without changes
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"""Mirror panel PSF calculation."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
import astropy.units as u
|
|
6
|
+
import numpy as np
|
|
7
|
+
from astropy.table import QTable, Table
|
|
8
|
+
|
|
9
|
+
import simtools.data_model.model_data_writer as writer
|
|
10
|
+
import simtools.utils.general as gen
|
|
11
|
+
from simtools.data_model.metadata_collector import MetadataCollector
|
|
12
|
+
from simtools.model.telescope_model import TelescopeModel
|
|
13
|
+
from simtools.ray_tracing.ray_tracing import RayTracing
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MirrorPanelPSF:
|
|
17
|
+
"""
|
|
18
|
+
Mirror panel PSF and random reflection angle calculation.
|
|
19
|
+
|
|
20
|
+
This class is used to derive the random reflection angle for the mirror panels in the telescope.
|
|
21
|
+
|
|
22
|
+
Known limitations: single Gaussian PSF model, no support for multiple PSF components (as allowed
|
|
23
|
+
in the model parameters).
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
label: str
|
|
28
|
+
Application label.
|
|
29
|
+
args_dict: dict
|
|
30
|
+
Dictionary with input arguments.
|
|
31
|
+
db_config:
|
|
32
|
+
Dictionary with database configuration.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, label, args_dict, db_config):
|
|
36
|
+
"""Initialize the MirrorPanelPSF class."""
|
|
37
|
+
self._logger = logging.getLogger(__name__)
|
|
38
|
+
self._logger.debug("Initializing MirrorPanelPSF")
|
|
39
|
+
|
|
40
|
+
self.args_dict = args_dict
|
|
41
|
+
self.telescope_model = self._define_telescope_model(label, db_config)
|
|
42
|
+
|
|
43
|
+
if self.args_dict["test"]:
|
|
44
|
+
self.args_dict["number_of_mirrors_to_test"] = 2
|
|
45
|
+
|
|
46
|
+
if self.args_dict["psf_measurement"]:
|
|
47
|
+
self._get_psf_containment()
|
|
48
|
+
if not self.args_dict["psf_measurement_containment_mean"]:
|
|
49
|
+
raise ValueError("Missing PSF measurement")
|
|
50
|
+
|
|
51
|
+
self.mean_d80 = None
|
|
52
|
+
self.sig_d80 = None
|
|
53
|
+
self.rnda_start = self._get_starting_value()
|
|
54
|
+
self.rnda_opt = None
|
|
55
|
+
self.results_rnda = []
|
|
56
|
+
self.results_mean = []
|
|
57
|
+
self.results_sig = []
|
|
58
|
+
|
|
59
|
+
def _define_telescope_model(self, label, db_config):
|
|
60
|
+
"""
|
|
61
|
+
Define telescope model.
|
|
62
|
+
|
|
63
|
+
This includes updating the configuration with mirror list and/or random focal length given
|
|
64
|
+
as input.
|
|
65
|
+
|
|
66
|
+
Attributes
|
|
67
|
+
----------
|
|
68
|
+
label: str
|
|
69
|
+
Application label.
|
|
70
|
+
db_config:
|
|
71
|
+
Dictionary with database configuration.
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
-------
|
|
75
|
+
tel TelescopeModel
|
|
76
|
+
telescope model
|
|
77
|
+
|
|
78
|
+
"""
|
|
79
|
+
tel = TelescopeModel(
|
|
80
|
+
site=self.args_dict["site"],
|
|
81
|
+
telescope_name=self.args_dict["telescope"],
|
|
82
|
+
model_version=self.args_dict["model_version"],
|
|
83
|
+
mongo_db_config=db_config,
|
|
84
|
+
label=label,
|
|
85
|
+
)
|
|
86
|
+
if self.args_dict["mirror_list"] is not None:
|
|
87
|
+
mirror_list_file = gen.find_file(
|
|
88
|
+
name=self.args_dict["mirror_list"], loc=self.args_dict["model_path"]
|
|
89
|
+
)
|
|
90
|
+
tel.change_parameter("mirror_list", self.args_dict["mirror_list"])
|
|
91
|
+
tel.export_parameter_file("mirror_list", mirror_list_file)
|
|
92
|
+
if self.args_dict["random_focal_length"] is not None:
|
|
93
|
+
tel.change_parameter("random_focal_length", str(self.args_dict["random_focal_length"]))
|
|
94
|
+
tel.export_model_files()
|
|
95
|
+
|
|
96
|
+
return tel
|
|
97
|
+
|
|
98
|
+
def _get_psf_containment(self):
|
|
99
|
+
"""Read measured single-mirror point-spread function from file and return mean and sigma."""
|
|
100
|
+
# If this is a test, read just the first few lines since we only simulate those mirrors
|
|
101
|
+
data_end = (
|
|
102
|
+
self.args_dict["number_of_mirrors_to_test"] + 1 if self.args_dict["test"] else None
|
|
103
|
+
)
|
|
104
|
+
_psf_list = Table.read(
|
|
105
|
+
self.args_dict["psf_measurement"], format="ascii.ecsv", data_end=data_end
|
|
106
|
+
)
|
|
107
|
+
try:
|
|
108
|
+
self.args_dict["psf_measurement_containment_mean"] = np.nanmean(
|
|
109
|
+
np.array(_psf_list["psf_opt"].to("cm").value)
|
|
110
|
+
)
|
|
111
|
+
self.args_dict["psf_measurement_containment_sigma"] = np.nanstd(
|
|
112
|
+
np.array(_psf_list["psf_opt"].to("cm").value)
|
|
113
|
+
)
|
|
114
|
+
except KeyError as exc:
|
|
115
|
+
raise KeyError(
|
|
116
|
+
f"Missing column psf measurement (psf_opt) in {self.args_dict['psf_measurement']}"
|
|
117
|
+
) from exc
|
|
118
|
+
|
|
119
|
+
self._logger.info(
|
|
120
|
+
f"Determined PSF containment to {self.args_dict['psf_measurement_containment_mean']:.4}"
|
|
121
|
+
f" +- {self.args_dict['psf_measurement_containment_sigma']:.4} cm"
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
def derive_random_reflection_angle(self, save_figures=False):
|
|
125
|
+
"""
|
|
126
|
+
Minimize the difference between measured and simulated PSF for reflection angle.
|
|
127
|
+
|
|
128
|
+
Main loop of the optimization process. The method iterates over different values of the
|
|
129
|
+
random reflection angle until the difference in the mean value of the D80 containment
|
|
130
|
+
is minimal.
|
|
131
|
+
"""
|
|
132
|
+
if self.args_dict["no_tuning"]:
|
|
133
|
+
self.rnda_opt = self.rnda_start
|
|
134
|
+
else:
|
|
135
|
+
self._optimize_reflection_angle()
|
|
136
|
+
|
|
137
|
+
self.mean_d80, self.sig_d80 = self.run_simulations_and_analysis(
|
|
138
|
+
self.rnda_opt, save_figures=save_figures
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
def _optimize_reflection_angle(self, step_size=0.1):
|
|
142
|
+
"""Optimize the random reflection angle to minimize the difference in D80 containment."""
|
|
143
|
+
|
|
144
|
+
def collect_results(rnda, mean, sig):
|
|
145
|
+
self.results_rnda.append(rnda)
|
|
146
|
+
self.results_mean.append(mean)
|
|
147
|
+
self.results_sig.append(sig)
|
|
148
|
+
|
|
149
|
+
stop = False
|
|
150
|
+
mean_d80, sig_d80 = self.run_simulations_and_analysis(self.rnda_start)
|
|
151
|
+
rnda = self.rnda_start
|
|
152
|
+
sign_delta = np.sign(mean_d80 - self.args_dict["psf_measurement_containment_mean"])
|
|
153
|
+
collect_results(rnda, mean_d80, sig_d80)
|
|
154
|
+
while not stop:
|
|
155
|
+
rnda = rnda - (step_size * self.rnda_start * sign_delta)
|
|
156
|
+
if rnda < 0:
|
|
157
|
+
rnda = 0
|
|
158
|
+
collect_results(rnda, mean_d80, sig_d80)
|
|
159
|
+
break
|
|
160
|
+
mean_d80, sig_d80 = self.run_simulations_and_analysis(rnda)
|
|
161
|
+
new_sign_delta = np.sign(mean_d80 - self.args_dict["psf_measurement_containment_mean"])
|
|
162
|
+
stop = new_sign_delta != sign_delta
|
|
163
|
+
sign_delta = new_sign_delta
|
|
164
|
+
collect_results(rnda, mean_d80, sig_d80)
|
|
165
|
+
|
|
166
|
+
self._interpolate_optimal_rnda()
|
|
167
|
+
|
|
168
|
+
def _interpolate_optimal_rnda(self):
|
|
169
|
+
"""Interpolate to find the optimal random reflection angle."""
|
|
170
|
+
self.results_rnda, self.results_mean, self.results_sig = gen.sort_arrays(
|
|
171
|
+
self.results_rnda, self.results_mean, self.results_sig
|
|
172
|
+
)
|
|
173
|
+
self.rnda_opt = np.interp(
|
|
174
|
+
x=self.args_dict["psf_measurement_containment_mean"],
|
|
175
|
+
xp=self.results_mean,
|
|
176
|
+
fp=self.results_rnda,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
def _get_starting_value(self):
|
|
180
|
+
"""Get optimization starting value from command line or previous model."""
|
|
181
|
+
if self.args_dict["rnda"] != 0:
|
|
182
|
+
rnda_start = self.args_dict["rnda"]
|
|
183
|
+
else:
|
|
184
|
+
rnda_start = self.telescope_model.get_parameter_value("mirror_reflection_random_angle")[
|
|
185
|
+
0
|
|
186
|
+
]
|
|
187
|
+
|
|
188
|
+
self._logger.info(f"Start value for mirror_reflection_random_angle: {rnda_start} deg")
|
|
189
|
+
return rnda_start
|
|
190
|
+
|
|
191
|
+
def run_simulations_and_analysis(self, rnda, save_figures=False):
|
|
192
|
+
"""
|
|
193
|
+
Run ray tracing simulations and analysis for one given value of rnda.
|
|
194
|
+
|
|
195
|
+
Parameters
|
|
196
|
+
----------
|
|
197
|
+
rnda: float
|
|
198
|
+
Random reflection angle in degrees.
|
|
199
|
+
save_figures: bool
|
|
200
|
+
Save figures.
|
|
201
|
+
|
|
202
|
+
Returns
|
|
203
|
+
-------
|
|
204
|
+
mean_d80: float
|
|
205
|
+
Mean value of D80 in cm.
|
|
206
|
+
sig_d80: float
|
|
207
|
+
Standard deviation of D80 in cm.
|
|
208
|
+
"""
|
|
209
|
+
self.telescope_model.change_parameter("mirror_reflection_random_angle", rnda)
|
|
210
|
+
ray = RayTracing(
|
|
211
|
+
telescope_model=self.telescope_model,
|
|
212
|
+
simtel_path=self.args_dict.get("simtel_path", None),
|
|
213
|
+
single_mirror_mode=True,
|
|
214
|
+
mirror_numbers=(
|
|
215
|
+
list(range(1, self.args_dict["number_of_mirrors_to_test"] + 1))
|
|
216
|
+
if self.args_dict["test"]
|
|
217
|
+
else "all"
|
|
218
|
+
),
|
|
219
|
+
use_random_focal_length=self.args_dict["use_random_focal_length"],
|
|
220
|
+
)
|
|
221
|
+
ray.simulate(test=self.args_dict["test"], force=True) # force has to be True, always
|
|
222
|
+
ray.analyze(force=True)
|
|
223
|
+
if save_figures:
|
|
224
|
+
ray.plot("d80_cm", save=True, d80=self.args_dict["psf_measurement_containment_mean"])
|
|
225
|
+
|
|
226
|
+
return (
|
|
227
|
+
ray.get_mean("d80_cm").to(u.cm).value,
|
|
228
|
+
ray.get_std_dev("d80_cm").to(u.cm).value,
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
def print_results(self):
|
|
232
|
+
"""Print results to stdout."""
|
|
233
|
+
containment_fraction_percent = int(self.args_dict["containment_fraction"] * 100)
|
|
234
|
+
|
|
235
|
+
print(f"\nMeasured D{containment_fraction_percent}:")
|
|
236
|
+
if self.args_dict["psf_measurement_containment_sigma"] is not None:
|
|
237
|
+
print(
|
|
238
|
+
f"Mean = {self.args_dict['psf_measurement_containment_mean']:.3f} cm, "
|
|
239
|
+
f"StdDev = {self.args_dict['psf_measurement_containment_sigma']:.3f} cm"
|
|
240
|
+
)
|
|
241
|
+
else:
|
|
242
|
+
print(f"Mean = {self.args_dict['psf_measurement_containment_mean']:.3f} cm")
|
|
243
|
+
print(f"\nSimulated D{containment_fraction_percent}:")
|
|
244
|
+
print(f"Mean = {self.mean_d80:.3f} cm, StdDev = {self.sig_d80:.3f} cm")
|
|
245
|
+
print("\nmirror_random_reflection_angle")
|
|
246
|
+
print(f"Previous value = {self.rnda_start:.6f}")
|
|
247
|
+
print(f"New value = {self.rnda_opt:.6f}\n")
|
|
248
|
+
|
|
249
|
+
def write_optimization_data(self):
|
|
250
|
+
"""
|
|
251
|
+
Write optimization results to an astropy table (ecsv file).
|
|
252
|
+
|
|
253
|
+
Used mostly for debugging of the optimization process.
|
|
254
|
+
The first entry of the table is the best fit result.
|
|
255
|
+
"""
|
|
256
|
+
containment_fraction_percent = int(self.args_dict["containment_fraction"] * 100)
|
|
257
|
+
|
|
258
|
+
result_table = QTable(
|
|
259
|
+
[
|
|
260
|
+
[True] + [False] * len(self.results_rnda),
|
|
261
|
+
[self.rnda_opt, *self.results_rnda] * u.deg,
|
|
262
|
+
([0.0] * (len(self.results_rnda) + 1)),
|
|
263
|
+
([0.0] * (len(self.results_rnda) + 1)) * u.deg,
|
|
264
|
+
[self.mean_d80, *self.results_mean] * u.cm,
|
|
265
|
+
[self.sig_d80, *self.results_sig] * u.cm,
|
|
266
|
+
],
|
|
267
|
+
names=(
|
|
268
|
+
"best_fit",
|
|
269
|
+
"mirror_reflection_random_angle_sigma1",
|
|
270
|
+
"mirror_reflection_random_angle_fraction2",
|
|
271
|
+
"mirror_reflection_random_angle_sigma2",
|
|
272
|
+
f"containment_radius_D{containment_fraction_percent}",
|
|
273
|
+
f"containment_radius_sigma_D{containment_fraction_percent}",
|
|
274
|
+
),
|
|
275
|
+
)
|
|
276
|
+
writer.ModelDataWriter.dump(
|
|
277
|
+
args_dict=self.args_dict,
|
|
278
|
+
metadata=MetadataCollector(args_dict=self.args_dict).top_level_meta,
|
|
279
|
+
product_data=result_table,
|
|
280
|
+
)
|