gammasimtools 0.18.0__py3-none-any.whl → 0.20.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/METADATA +24 -69
- gammasimtools-0.20.0.dist-info/RECORD +395 -0
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/entry_points.txt +11 -4
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/licenses/LICENSE +1 -1
- simtools/_version.py +16 -3
- simtools/applications/calculate_incident_angles.py +182 -0
- simtools/applications/convert_all_model_parameters_from_simtel.py +4 -3
- simtools/applications/convert_geo_coordinates_of_array_elements.py +3 -3
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +17 -14
- simtools/applications/db_add_value_from_json_to_db.py +8 -10
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +8 -13
- simtools/applications/db_generate_compound_indexes.py +65 -0
- simtools/applications/db_get_file_from_db.py +12 -24
- simtools/applications/db_get_parameter_from_db.py +4 -4
- simtools/applications/db_inspect_databases.py +20 -10
- simtools/applications/derive_mirror_rnda.py +17 -11
- simtools/applications/derive_psf_parameters.py +59 -309
- simtools/applications/derive_trigger_rates.py +91 -0
- simtools/applications/docs_produce_array_element_report.py +1 -1
- simtools/applications/docs_produce_calibration_reports.py +1 -1
- simtools/applications/docs_produce_model_parameter_reports.py +1 -1
- simtools/applications/docs_produce_simulation_configuration_report.py +1 -1
- simtools/applications/generate_corsika_histograms.py +1 -1
- simtools/applications/generate_default_metadata.py +8 -24
- simtools/applications/generate_simtel_event_data.py +11 -11
- simtools/applications/maintain_simulation_model_add_production_table.py +71 -0
- simtools/applications/maintain_simulation_model_compare_productions.py +98 -0
- simtools/applications/{verify_simulation_model_production_tables.py → maintain_simulation_model_verify_production_tables.py} +9 -1
- simtools/applications/merge_tables.py +2 -2
- simtools/applications/plot_array_layout.py +3 -3
- simtools/applications/plot_simtel_events.py +421 -0
- simtools/applications/plot_tabular_data.py +9 -2
- simtools/applications/plot_tabular_data_for_model_parameter.py +2 -1
- simtools/applications/print_version.py +8 -9
- simtools/applications/production_derive_corsika_limits.py +6 -7
- simtools/applications/production_derive_statistics.py +1 -1
- simtools/applications/production_generate_grid.py +2 -2
- simtools/applications/production_merge_corsika_limits.py +214 -0
- simtools/applications/run_application.py +47 -113
- simtools/applications/simulate_calibration_events.py +166 -0
- simtools/applications/simulate_flasher.py +141 -0
- simtools/applications/{simulate_light_emission.py → simulate_illuminator.py} +35 -99
- simtools/applications/simulate_prod.py +6 -24
- simtools/applications/simulate_prod_htcondor_generator.py +7 -0
- simtools/applications/submit_array_layouts.py +2 -1
- simtools/applications/submit_model_parameter_from_external.py +1 -1
- simtools/applications/validate_camera_efficiency.py +30 -12
- simtools/applications/validate_camera_fov.py +1 -1
- simtools/applications/validate_cumulative_psf.py +1 -1
- simtools/applications/validate_file_using_schema.py +9 -5
- simtools/applications/validate_optics.py +1 -1
- simtools/camera/camera_efficiency.py +61 -45
- simtools/camera/single_photon_electron_spectrum.py +1 -1
- simtools/configuration/commandline_parser.py +46 -11
- simtools/configuration/configurator.py +4 -4
- simtools/corsika/corsika_config.py +45 -25
- simtools/corsika/corsika_histograms.py +6 -5
- simtools/data_model/data_reader.py +2 -3
- simtools/data_model/metadata_collector.py +32 -36
- simtools/data_model/metadata_model.py +15 -12
- simtools/data_model/model_data_writer.py +13 -32
- simtools/data_model/schema.py +74 -24
- simtools/data_model/validate_data.py +42 -12
- simtools/db/db_handler.py +125 -62
- simtools/db/db_model_upload.py +14 -19
- simtools/dependencies.py +98 -30
- simtools/io/ascii_handler.py +279 -0
- simtools/{io_operations → io}/io_handler.py +25 -3
- simtools/job_execution/htcondor_script_generator.py +15 -4
- simtools/layout/array_layout.py +1 -1
- simtools/layout/array_layout_utils.py +51 -12
- simtools/model/array_model.py +41 -5
- simtools/model/flasher_model.py +106 -0
- simtools/model/model_parameter.py +4 -4
- simtools/model/model_repository.py +197 -2
- simtools/model/site_model.py +25 -0
- simtools/model/telescope_model.py +3 -1
- simtools/production_configuration/derive_corsika_limits.py +336 -427
- simtools/production_configuration/derive_production_statistics_handler.py +7 -6
- simtools/production_configuration/generate_production_grid.py +9 -11
- simtools/production_configuration/merge_corsika_limits.py +528 -0
- simtools/ray_tracing/incident_angles.py +706 -0
- simtools/ray_tracing/mirror_panel_psf.py +1 -0
- simtools/ray_tracing/psf_parameter_optimisation.py +792 -0
- simtools/ray_tracing/ray_tracing.py +6 -2
- simtools/reporting/docs_read_parameters.py +150 -62
- simtools/runners/corsika_runner.py +1 -1
- simtools/runners/corsika_simtel_runner.py +14 -5
- simtools/runners/runner_services.py +10 -5
- simtools/runners/simtools_runner.py +267 -0
- simtools/schemas/application_workflow.metaschema.yml +101 -68
- simtools/schemas/input/MST_mirror_2f_measurements.schema.yml +1 -1
- simtools/schemas/input/single_pe_spectrum.schema.yml +1 -1
- simtools/schemas/metadata.metaschema.yml +577 -3
- simtools/schemas/model_parameter.metaschema.yml +6 -6
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +4 -4
- simtools/schemas/model_parameters/adjust_gain.schema.yml +1 -1
- simtools/schemas/model_parameters/altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/array_coordinates.schema.yml +1 -1
- simtools/schemas/model_parameters/array_coordinates_UTM.schema.yml +1 -1
- simtools/schemas/model_parameters/array_element_position_ground.schema.yml +1 -1
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +1 -1
- simtools/schemas/model_parameters/array_layouts.schema.yml +1 -1
- simtools/schemas/model_parameters/array_triggers.schema.yml +1 -1
- simtools/schemas/model_parameters/array_window.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_shaping.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/atmospheric_profile.schema.yml +1 -1
- simtools/schemas/model_parameters/atmospheric_transmission.schema.yml +1 -1
- simtools/schemas/model_parameters/axes_offsets.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_body_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_body_shape.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_config_file.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_config_rotate.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_depth.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_filter.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_filter_incidence_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_pixels.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_transmission.schema.yml +1 -1
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
- simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_cherenkov_photon_bunch_size.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_cherenkov_photon_wavelength_range.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_first_interaction_height.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_longitudinal_shower_development.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_observation_level.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_particle_kinetic_energy_cutoff.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +3 -3
- simtools/schemas/model_parameters/dark_events.schema.yml +1 -1
- simtools/schemas/model_parameters/default_trigger.schema.yml +1 -1
- simtools/schemas/model_parameters/design_model.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_ac_coupled.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_start.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/dish_shape_length.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_pedsub.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +1 -1
- simtools/schemas/model_parameters/effective_focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/epsg_code.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_ac_coupled.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_long_event_threshold.schema.yml +35 -0
- simtools/schemas/model_parameters/fadc_long_sum_bins.schema.yml +41 -0
- simtools/schemas/model_parameters/fadc_long_sum_offset.schema.yml +38 -0
- simtools/schemas/model_parameters/fadc_max_signal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_max_sum.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_mhz.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_noise.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fake_mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/flatfielding.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_surface_parameters.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_surface_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/focus_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/gain_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_horizontal.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_rotation.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_vertical.schema.yml +1 -1
- simtools/schemas/model_parameters/hg_lg_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_events.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_external_trigger.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_exptime.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_sigtime.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_twidth.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_var_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_wavelength.schema.yml +1 -1
- simtools/schemas/model_parameters/led_events.schema.yml +1 -1
- simtools/schemas/model_parameters/led_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/led_pulse_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/led_pulse_sigtime.schema.yml +1 -1
- simtools/schemas/model_parameters/led_var_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +50 -1
- simtools/schemas/model_parameters/min_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/min_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_class.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_panel_2f_measurements.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +1 -1
- simtools/schemas/model_parameters/multiplicity_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/muon_mono_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_gain_drop_scale.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_offaxis.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +2 -2
- simtools/schemas/model_parameters/nsb_reference_value.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_scaling_factor.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_sky_map.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_spectrum.schema.yml +23 -30
- simtools/schemas/model_parameters/num_gains.schema.yml +1 -1
- simtools/schemas/model_parameters/only_triggered_telescopes.schema.yml +1 -1
- simtools/schemas/model_parameters/optics_properties.schema.yml +1 -1
- simtools/schemas/model_parameters/parabolic_dish.schema.yml +1 -1
- simtools/schemas/model_parameters/pedestal_events.schema.yml +1 -1
- simtools/schemas/model_parameters/photon_delay.schema.yml +1 -1
- simtools/schemas/model_parameters/photons_per_run.schema.yml +1 -1
- simtools/schemas/model_parameters/pixel_cells.schema.yml +1 -1
- simtools/schemas/model_parameters/pixels_parallel.schema.yml +1 -1
- simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_average_gain.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_gain_index.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_transit_time.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_hole_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_incidence_angle.schema.yml +11 -1
- simtools/schemas/model_parameters/primary_mirror_parameters.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_segmentation.schema.yml +1 -1
- simtools/schemas/model_parameters/qe_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/quantum_efficiency.schema.yml +1 -1
- simtools/schemas/model_parameters/random_focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/random_generator.schema.yml +1 -1
- simtools/schemas/model_parameters/random_mono_probability.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_latitude.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_longitude.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_utm_east.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_utm_north.schema.yml +1 -1
- simtools/schemas/model_parameters/sampled_output.schema.yml +1 -1
- simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_baffle.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_hole_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_incidence_angle.schema.yml +11 -1
- simtools/schemas/model_parameters/secondary_mirror_parameters.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_reflectivity.schema.yml +11 -1
- simtools/schemas/model_parameters/secondary_mirror_segmentation.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_shadow_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_shadow_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/stars.schema.yml +2 -2
- simtools/schemas/model_parameters/store_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/tailcut_scale.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_axis_height.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_random_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_random_error.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_transmission.schema.yml +1 -1
- simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +1 -1
- simtools/schemas/model_parameters/teltrig_min_time.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_jitter.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_current_limit.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_pixels.schema.yml +1 -1
- simtools/schemas/plot_configuration.metaschema.yml +5 -2
- simtools/schemas/production_configuration_metrics.schema.yml +12 -2
- simtools/schemas/production_tables.schema.yml +7 -2
- simtools/simtel/simtel_config_reader.py +2 -2
- simtools/simtel/simtel_config_writer.py +33 -23
- simtools/simtel/simtel_io_event_histograms.py +483 -0
- simtools/simtel/simtel_io_event_reader.py +65 -43
- simtools/simtel/simtel_io_event_writer.py +40 -20
- simtools/simtel/simtel_io_metadata.py +1 -1
- simtools/simtel/simtel_table_reader.py +95 -13
- simtools/simtel/simulator_array.py +138 -10
- simtools/simtel/simulator_camera_efficiency.py +32 -23
- simtools/simtel/simulator_light_emission.py +437 -271
- simtools/simtel/simulator_ray_tracing.py +1 -1
- simtools/simulator.py +105 -147
- simtools/telescope_trigger_rates.py +119 -0
- simtools/testing/configuration.py +24 -26
- simtools/testing/helpers.py +2 -2
- simtools/testing/log_inspector.py +52 -0
- simtools/testing/validate_output.py +87 -37
- simtools/utils/general.py +125 -255
- simtools/utils/geometry.py +56 -0
- simtools/utils/names.py +1 -1
- simtools/visualization/legend_handlers.py +180 -264
- simtools/visualization/plot_array_layout.py +20 -8
- simtools/visualization/plot_incident_angles.py +431 -0
- simtools/visualization/plot_pixels.py +1 -1
- simtools/visualization/plot_simtel_event_histograms.py +376 -0
- simtools/visualization/plot_simtel_events.py +816 -0
- simtools/visualization/plot_tables.py +133 -37
- simtools/visualization/visualize.py +1 -100
- gammasimtools-0.18.0.dist-info/RECORD +0 -376
- simtools/applications/calculate_trigger_rate.py +0 -187
- simtools/applications/generate_sim_telarray_histograms.py +0 -196
- simtools/production_configuration/derive_corsika_limits_grid.py +0 -232
- simtools/simtel/simtel_io_histogram.py +0 -621
- simtools/simtel/simtel_io_histograms.py +0 -552
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/top_level.txt +0 -0
- /simtools/{io_operations → io}/hdf5_handler.py +0 -0
- /simtools/{io_operations → io}/legacy_data_handler.py +0 -0
- /simtools/{io_operations/io_table_handler.py → io/table_handler.py} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
"""Simulation using the light emission package for calibration."""
|
|
1
|
+
"""Simulation using the light emission package for calibration devices."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
import shutil
|
|
4
5
|
import stat
|
|
5
6
|
import subprocess
|
|
6
7
|
from pathlib import Path
|
|
@@ -8,11 +9,9 @@ from pathlib import Path
|
|
|
8
9
|
import astropy.units as u
|
|
9
10
|
import numpy as np
|
|
10
11
|
|
|
11
|
-
from simtools.
|
|
12
|
-
from simtools.io_operations import io_handler
|
|
12
|
+
from simtools.io import io_handler
|
|
13
13
|
from simtools.runners.simtel_runner import SimtelRunner
|
|
14
14
|
from simtools.utils.general import clear_default_sim_telarray_cfg_directories
|
|
15
|
-
from simtools.visualization.visualize import plot_simtel_ctapipe
|
|
16
15
|
|
|
17
16
|
__all__ = ["SimulatorLightEmission"]
|
|
18
17
|
|
|
@@ -26,47 +25,104 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
26
25
|
|
|
27
26
|
def __init__(
|
|
28
27
|
self,
|
|
28
|
+
*,
|
|
29
29
|
telescope_model,
|
|
30
|
-
calibration_model,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
calibration_model=None,
|
|
31
|
+
flasher_model=None,
|
|
32
|
+
site_model=None,
|
|
33
|
+
light_emission_config=None,
|
|
34
|
+
light_source_setup=None,
|
|
35
|
+
simtel_path=None,
|
|
36
|
+
light_source_type=None,
|
|
36
37
|
label=None,
|
|
37
38
|
test=False,
|
|
38
39
|
):
|
|
39
|
-
"""Initialize SimtelRunner.
|
|
40
|
-
|
|
40
|
+
"""Initialize SimtelRunner.
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
telescope_model : TelescopeModel
|
|
45
|
+
Model of the telescope to be simulated
|
|
46
|
+
calibration_model : CalibrationModel, optional
|
|
47
|
+
Model of the calibration device to be simulated
|
|
48
|
+
flasher_model : FlasherModel, optional
|
|
49
|
+
Model of the flasher device to be simulated
|
|
50
|
+
site_model : SiteModel, optional
|
|
51
|
+
Model of the site
|
|
52
|
+
light_emission_config : dict, optional
|
|
53
|
+
Configuration for the light emission
|
|
54
|
+
light_source_setup : str, optional
|
|
55
|
+
Setup for light source positioning ("variable" or "layout")
|
|
56
|
+
simtel_path : Path, optional
|
|
57
|
+
Path to the sim_telarray installation
|
|
58
|
+
light_source_type : str, optional
|
|
59
|
+
Type of light source: 'illuminator', or 'flasher'
|
|
60
|
+
label : str, optional
|
|
61
|
+
Label for the simulation
|
|
62
|
+
test : bool, optional
|
|
63
|
+
Whether this is a test run
|
|
64
|
+
"""
|
|
65
|
+
super().__init__(simtel_path=simtel_path, label=label, corsika_config=None)
|
|
41
66
|
|
|
42
67
|
self._logger = logging.getLogger(__name__)
|
|
43
|
-
self._logger.debug("Init SimtelRunnerLightEmission")
|
|
44
|
-
self._simtel_path = simtel_path
|
|
45
68
|
|
|
46
69
|
self._telescope_model = telescope_model
|
|
47
|
-
|
|
48
|
-
self.label = label if label is not None else self._telescope_model.label
|
|
49
|
-
self.test = test
|
|
50
|
-
|
|
51
70
|
self._calibration_model = calibration_model
|
|
71
|
+
self._flasher_model = flasher_model
|
|
52
72
|
self._site_model = site_model
|
|
73
|
+
self.light_emission_config = light_emission_config or {}
|
|
74
|
+
self.light_source_setup = light_source_setup
|
|
75
|
+
self.light_source_type = light_source_type or "illuminator"
|
|
76
|
+
self.test = test
|
|
77
|
+
|
|
78
|
+
# IO
|
|
53
79
|
self.io_handler = io_handler.IOHandler()
|
|
54
80
|
self.output_directory = self.io_handler.get_output_directory(self.label)
|
|
55
81
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
self.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
82
|
+
self.number_events = self.light_emission_config["number_events"]
|
|
83
|
+
|
|
84
|
+
# photons per run
|
|
85
|
+
if self._calibration_model is not None:
|
|
86
|
+
self.photons_per_run = (
|
|
87
|
+
self._calibration_model.get_parameter_value("photons_per_run")
|
|
88
|
+
if not self.test
|
|
89
|
+
else 1e8
|
|
90
|
+
)
|
|
91
|
+
elif self._flasher_model is not None:
|
|
92
|
+
self.photons_per_run = (
|
|
93
|
+
self._flasher_model.get_parameter_value("photons_per_flasher")
|
|
94
|
+
if not self.test
|
|
95
|
+
else 1e8
|
|
96
|
+
)
|
|
97
|
+
else:
|
|
98
|
+
self.photons_per_run = 1e8
|
|
64
99
|
|
|
65
|
-
|
|
66
|
-
self.
|
|
100
|
+
# Ensure sim_telarray config exists on disk
|
|
101
|
+
if hasattr(self._telescope_model, "write_sim_telarray_config_file"):
|
|
102
|
+
self._telescope_model.write_sim_telarray_config_file(additional_model=site_model)
|
|
103
|
+
|
|
104
|
+
# Runtime variables
|
|
67
105
|
self.distance = None
|
|
68
|
-
|
|
69
|
-
|
|
106
|
+
|
|
107
|
+
def _get_prefix(self) -> str:
|
|
108
|
+
prefix = self.light_emission_config.get("output_prefix", "")
|
|
109
|
+
if prefix is not None:
|
|
110
|
+
return f"{prefix}_"
|
|
111
|
+
return ""
|
|
112
|
+
|
|
113
|
+
def _infer_application(self) -> tuple[str, str]:
|
|
114
|
+
"""Infer the LightEmission application and mode from type/setup.
|
|
115
|
+
|
|
116
|
+
Returns
|
|
117
|
+
-------
|
|
118
|
+
tuple[str, str]
|
|
119
|
+
(app_name, mode)
|
|
120
|
+
"""
|
|
121
|
+
if self.light_source_type == "flasher":
|
|
122
|
+
return ("ff-1m", "flasher")
|
|
123
|
+
# default to illuminator xyzls, mode from setup
|
|
124
|
+
mode = self.light_source_setup or "layout"
|
|
125
|
+
return ("xyzls", mode)
|
|
70
126
|
|
|
71
127
|
@staticmethod
|
|
72
128
|
def light_emission_default_configuration():
|
|
@@ -112,6 +168,79 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
112
168
|
},
|
|
113
169
|
}
|
|
114
170
|
|
|
171
|
+
@staticmethod
|
|
172
|
+
def flasher_default_configuration():
|
|
173
|
+
"""
|
|
174
|
+
Get default flasher configuration.
|
|
175
|
+
|
|
176
|
+
Returns
|
|
177
|
+
-------
|
|
178
|
+
dict
|
|
179
|
+
Default configuration for flasher devices.
|
|
180
|
+
"""
|
|
181
|
+
return {
|
|
182
|
+
"number_events": {
|
|
183
|
+
"len": 1,
|
|
184
|
+
"unit": None,
|
|
185
|
+
"default": 1,
|
|
186
|
+
"names": ["number_events"],
|
|
187
|
+
},
|
|
188
|
+
"photons_per_flasher": {
|
|
189
|
+
"len": 1,
|
|
190
|
+
"unit": None,
|
|
191
|
+
"default": 2.5e6,
|
|
192
|
+
"names": ["photons"],
|
|
193
|
+
},
|
|
194
|
+
"bunch_size": {
|
|
195
|
+
"len": 1,
|
|
196
|
+
"unit": None,
|
|
197
|
+
"default": 1.0,
|
|
198
|
+
"names": ["bunchsize"],
|
|
199
|
+
},
|
|
200
|
+
"flasher_position": {
|
|
201
|
+
"len": 2,
|
|
202
|
+
"unit": u.Unit("cm"),
|
|
203
|
+
"default": [0.0, 0.0] * u.cm,
|
|
204
|
+
"names": ["xy", "position"],
|
|
205
|
+
},
|
|
206
|
+
"flasher_depth": {
|
|
207
|
+
"len": 1,
|
|
208
|
+
"unit": u.Unit("cm"),
|
|
209
|
+
"default": 60 * u.cm,
|
|
210
|
+
"names": ["depth", "distance"],
|
|
211
|
+
},
|
|
212
|
+
"flasher_inclination": {
|
|
213
|
+
"len": 1,
|
|
214
|
+
"unit": u.Unit("deg"),
|
|
215
|
+
"default": 0.0 * u.deg,
|
|
216
|
+
"names": ["inclination"],
|
|
217
|
+
},
|
|
218
|
+
"spectrum": {
|
|
219
|
+
"len": 1,
|
|
220
|
+
"unit": u.Unit("nm"),
|
|
221
|
+
"default": 400 * u.nm,
|
|
222
|
+
"names": ["wavelength"],
|
|
223
|
+
},
|
|
224
|
+
"lightpulse": {
|
|
225
|
+
"len": 1,
|
|
226
|
+
"unit": None,
|
|
227
|
+
"default": "Simple:0",
|
|
228
|
+
"names": ["pulse"],
|
|
229
|
+
},
|
|
230
|
+
"angular_distribution": {
|
|
231
|
+
"len": 1,
|
|
232
|
+
"unit": None,
|
|
233
|
+
"default": "isotropic",
|
|
234
|
+
"names": ["angular"],
|
|
235
|
+
},
|
|
236
|
+
"flasher_pattern": {
|
|
237
|
+
"len": 1,
|
|
238
|
+
"unit": None,
|
|
239
|
+
"default": "all",
|
|
240
|
+
"names": ["fire", "pattern"],
|
|
241
|
+
},
|
|
242
|
+
}
|
|
243
|
+
|
|
115
244
|
def calibration_pointing_direction(self):
|
|
116
245
|
"""
|
|
117
246
|
Calculate the pointing of the calibration device towards the telescope.
|
|
@@ -145,16 +274,16 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
145
274
|
tel_phi = 180 - np.round(
|
|
146
275
|
np.rad2deg(np.arctan2(direction_vector[1], direction_vector[0])), 6
|
|
147
276
|
)
|
|
148
|
-
|
|
149
|
-
# Calculate laser beam theta and phi angles
|
|
277
|
+
# Calculate source beam theta and phi angles
|
|
150
278
|
direction_vector_inv = direction_vector * -1
|
|
151
|
-
|
|
152
|
-
np.rad2deg(np.arccos(direction_vector_inv[2] / np.linalg.norm(direction_vector_inv))),
|
|
279
|
+
source_theta = np.round(
|
|
280
|
+
np.rad2deg(np.arccos(direction_vector_inv[2] / np.linalg.norm(direction_vector_inv))),
|
|
281
|
+
6,
|
|
153
282
|
)
|
|
154
|
-
|
|
283
|
+
source_phi = np.round(
|
|
155
284
|
np.rad2deg(np.arctan2(direction_vector_inv[1], direction_vector_inv[0])), 6
|
|
156
285
|
)
|
|
157
|
-
return pointing_vector.tolist(), [tel_theta, tel_phi,
|
|
286
|
+
return pointing_vector.tolist(), [tel_theta, tel_phi, source_theta, source_phi]
|
|
158
287
|
|
|
159
288
|
def _write_telpos_file(self):
|
|
160
289
|
"""
|
|
@@ -180,6 +309,30 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
180
309
|
|
|
181
310
|
return telpos_file
|
|
182
311
|
|
|
312
|
+
def _prepare_flasher_atmosphere_files(self, config_directory: Path) -> int:
|
|
313
|
+
"""Prepare canonical atmosphere aliases for ff-1m and return model id 1."""
|
|
314
|
+
atmo_name = self._site_model.get_parameter_value("atmospheric_profile")
|
|
315
|
+
self._logger.debug(f"Using atmosphere profile: {atmo_name}")
|
|
316
|
+
|
|
317
|
+
src_path = config_directory.joinpath(atmo_name)
|
|
318
|
+
for canonical in ("atmprof1.dat", "atm_profile_model_1.dat"):
|
|
319
|
+
dst = config_directory.joinpath(canonical)
|
|
320
|
+
if dst.exists() or dst.is_symlink():
|
|
321
|
+
try:
|
|
322
|
+
dst.unlink()
|
|
323
|
+
except OSError:
|
|
324
|
+
pass
|
|
325
|
+
try:
|
|
326
|
+
dst.symlink_to(src_path)
|
|
327
|
+
except OSError:
|
|
328
|
+
try:
|
|
329
|
+
shutil.copy2(src_path, dst)
|
|
330
|
+
except OSError as copy_err:
|
|
331
|
+
self._logger.warning(
|
|
332
|
+
f"Failed to create atmosphere alias {dst.name}: {copy_err}"
|
|
333
|
+
)
|
|
334
|
+
return 1
|
|
335
|
+
|
|
183
336
|
def _make_light_emission_script(self):
|
|
184
337
|
"""
|
|
185
338
|
Create the light emission script to run the light emission package.
|
|
@@ -192,92 +345,151 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
192
345
|
str
|
|
193
346
|
The commands to run the Light Emission package
|
|
194
347
|
"""
|
|
195
|
-
x_cal, y_cal, z_cal = self._calibration_model.get_parameter_value_with_unit(
|
|
196
|
-
"array_element_position_ground"
|
|
197
|
-
)
|
|
198
348
|
x_tel, y_tel, z_tel = self._telescope_model.get_parameter_value_with_unit(
|
|
199
349
|
"array_element_position_ground"
|
|
200
350
|
)
|
|
201
351
|
|
|
202
|
-
config_directory = self.io_handler.
|
|
203
|
-
label=self.label,
|
|
352
|
+
config_directory = self.io_handler.get_model_configuration_directory(
|
|
353
|
+
label=self.label, model_version=self._site_model.model_version
|
|
204
354
|
)
|
|
205
|
-
|
|
206
355
|
telpos_file = self._write_telpos_file()
|
|
207
356
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
357
|
+
app_name, _ = self._infer_application()
|
|
358
|
+
|
|
359
|
+
parts: list[str] = []
|
|
360
|
+
# application path
|
|
361
|
+
parts.append(str(self._simtel_path.joinpath("sim_telarray/LightEmission/")))
|
|
362
|
+
parts.append(f"/{app_name}")
|
|
363
|
+
|
|
212
364
|
corsika_observation_level = self._site_model.get_parameter_value_with_unit(
|
|
213
365
|
"corsika_observation_level"
|
|
214
366
|
)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
if self.light_source_type == "led":
|
|
219
|
-
if self.le_application[1] == "variable":
|
|
220
|
-
command += f" -x {self.light_emission_config['x_pos']['default'].to(u.cm).value}"
|
|
221
|
-
command += f" -y {self.light_emission_config['y_pos']['default'].to(u.cm).value}"
|
|
222
|
-
command += f" -z {self.light_emission_config['z_pos']['default'].to(u.cm).value}"
|
|
223
|
-
command += (
|
|
224
|
-
f" -d {','.join(map(str, self.light_emission_config['direction']['default']))}"
|
|
225
|
-
)
|
|
226
|
-
command += f" -n {self.photons_per_run}"
|
|
227
|
-
|
|
228
|
-
elif self.le_application[1] == "layout":
|
|
229
|
-
command += f" -x {x_cal.to(u.cm).value}"
|
|
230
|
-
command += f" -y {y_cal.to(u.cm).value}"
|
|
231
|
-
command += f" -z {z_cal.to(u.cm).value}"
|
|
232
|
-
pointing_vector = self.calibration_pointing_direction()[0]
|
|
233
|
-
command += f" -d {','.join(map(str, pointing_vector))}"
|
|
234
|
-
|
|
235
|
-
command += f" -n {self.photons_per_run}"
|
|
236
|
-
self._logger.info(f"Photons per run: {self.photons_per_run} ")
|
|
237
|
-
|
|
238
|
-
laser_wavelength = self._calibration_model.get_parameter_value_with_unit(
|
|
239
|
-
"laser_wavelength"
|
|
240
|
-
)
|
|
241
|
-
command += f" -s {int(laser_wavelength.to(u.nm).value)}"
|
|
242
|
-
|
|
243
|
-
led_pulse_sigtime = self._calibration_model.get_parameter_value_with_unit(
|
|
244
|
-
"led_pulse_sigtime"
|
|
245
|
-
)
|
|
246
|
-
command += f" -p Gauss:{led_pulse_sigtime.to(u.ns).value}"
|
|
247
|
-
command += " -a isotropic"
|
|
248
|
-
|
|
249
|
-
command += f" -A {config_directory}/"
|
|
250
|
-
command += f"{self._telescope_model.get_parameter_value('atmospheric_profile')}"
|
|
251
|
-
|
|
252
|
-
elif self.light_source_type == "laser":
|
|
253
|
-
command += " --events 1"
|
|
254
|
-
command += " --bunches 2500000"
|
|
255
|
-
command += " --step 0.1"
|
|
256
|
-
command += " --bunchsize 1"
|
|
257
|
-
spectrum = self._calibration_model.get_parameter_value_with_unit("laser_wavelength")
|
|
258
|
-
command += f" --spectrum {int(spectrum.to(u.nm).value)}"
|
|
259
|
-
command += " --lightpulse Gauss:"
|
|
260
|
-
pulse_sigtime = self._calibration_model.get_parameter_value_with_unit(
|
|
261
|
-
"laser_pulse_sigtime"
|
|
367
|
+
parts.append(
|
|
368
|
+
self._build_altitude_atmo_block(
|
|
369
|
+
app_name, config_directory, corsika_observation_level, telpos_file
|
|
262
370
|
)
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
parts.append(self._build_source_specific_block(x_tel, y_tel, z_tel, config_directory))
|
|
374
|
+
|
|
375
|
+
if self.light_source_type == "illuminator":
|
|
376
|
+
parts.append(f" -A {config_directory}/")
|
|
377
|
+
parts.append(f"{self._telescope_model.get_parameter_value('atmospheric_profile')}")
|
|
378
|
+
|
|
379
|
+
parts.append(f" -o {self.output_directory}/{app_name}.iact.gz")
|
|
380
|
+
parts.append("\n")
|
|
381
|
+
|
|
382
|
+
return "".join(parts)
|
|
383
|
+
|
|
384
|
+
def _build_altitude_atmo_block(
|
|
385
|
+
self, app_name, config_directory: Path, corsika_observation_level, telpos_file: Path
|
|
386
|
+
) -> str:
|
|
387
|
+
"""Return CLI segment for altitude/atmosphere and telpos handling."""
|
|
388
|
+
if app_name in ("ff-1m",):
|
|
389
|
+
seg = []
|
|
390
|
+
seg.append(" -I.")
|
|
391
|
+
seg.append(f" -I{self._simtel_path.joinpath('sim_telarray/cfg')}")
|
|
392
|
+
seg.append(f" -I{config_directory}")
|
|
393
|
+
seg.append(f" --altitude {corsika_observation_level.to(u.m).value}")
|
|
394
|
+
atmo_id = self._prepare_flasher_atmosphere_files(config_directory)
|
|
395
|
+
seg.append(f" --atmosphere {atmo_id}")
|
|
396
|
+
return "".join(seg)
|
|
397
|
+
# default path (not used for flasher now, but kept for completeness)
|
|
398
|
+
return f" -h {corsika_observation_level.to(u.m).value} --telpos-file {telpos_file}"
|
|
399
|
+
|
|
400
|
+
def _build_source_specific_block(self, _x_tel, _y_tel, _z_tel, _config_directory: Path) -> str:
|
|
401
|
+
"""Return CLI segment for light-source specific flags."""
|
|
402
|
+
if self.light_source_type == "flasher":
|
|
403
|
+
return self._add_flasher_command_options("")
|
|
404
|
+
if self.light_source_type == "illuminator":
|
|
405
|
+
return self._add_illuminator_command_options("")
|
|
406
|
+
self._logger.warning("Unknown light_source_type '%s'", self.light_source_type)
|
|
407
|
+
return ""
|
|
408
|
+
|
|
409
|
+
def _add_flasher_command_options(self, command):
|
|
410
|
+
"""Add flasher-specific options to the script (uniform ff-1m)."""
|
|
411
|
+
return self._add_flasher_options(command)
|
|
412
|
+
|
|
413
|
+
def _add_flasher_options(self, command):
|
|
414
|
+
"""Add flasher options for all telescope types (ff-1m style)."""
|
|
415
|
+
# For MST/LST we used to use ff-1m; now apply same for all telescopes
|
|
416
|
+
flasher_xy = self._flasher_model.get_parameter_value_with_unit("flasher_position")
|
|
417
|
+
flasher_distance = self._flasher_model.get_parameter_value_with_unit("flasher_depth")
|
|
418
|
+
# Camera radius required for application, Radius of fiducial sphere enclosing camera
|
|
419
|
+
camera_radius = (
|
|
420
|
+
self._telescope_model.get_parameter_value_with_unit("camera_body_diameter")
|
|
421
|
+
.to(u.cm)
|
|
422
|
+
.value
|
|
423
|
+
/ 2
|
|
424
|
+
)
|
|
425
|
+
spectrum = self._flasher_model.get_parameter_value_with_unit("spectrum")
|
|
426
|
+
pulse = self._flasher_model.get_parameter_value("lightpulse")
|
|
427
|
+
angular = self._flasher_model.get_parameter_value("angular_distribution")
|
|
428
|
+
bunch_size = self._flasher_model.get_parameter_value("bunch_size")
|
|
429
|
+
|
|
430
|
+
# Convert to plain numbers for CLI
|
|
431
|
+
fx = flasher_xy[0].to(u.cm).value
|
|
432
|
+
fy = flasher_xy[1].to(u.cm).value
|
|
433
|
+
dist_cm = flasher_distance.to(u.cm).value
|
|
434
|
+
spec_nm = int(spectrum.to(u.nm).value)
|
|
435
|
+
|
|
436
|
+
command += f" --events {self.number_events}"
|
|
437
|
+
command += f" --photons {self.photons_per_run}"
|
|
438
|
+
command += f" --bunchsize {bunch_size}"
|
|
439
|
+
command += f" --xy {fx},{fy}"
|
|
440
|
+
command += f" --distance {dist_cm}"
|
|
441
|
+
command += f" --camera-radius {camera_radius}"
|
|
442
|
+
command += f" --spectrum {spec_nm}"
|
|
443
|
+
command += f" --lightpulse {pulse}"
|
|
444
|
+
command += f" --angular-distribution {angular}"
|
|
445
|
+
return command
|
|
446
|
+
|
|
447
|
+
def _add_illuminator_command_options(self, command):
|
|
448
|
+
"""
|
|
449
|
+
Add illuminator-specific command options to the light emission script.
|
|
450
|
+
|
|
451
|
+
Parameters
|
|
452
|
+
----------
|
|
453
|
+
command : str
|
|
454
|
+
The command string to add options to
|
|
455
|
+
|
|
456
|
+
Returns
|
|
457
|
+
-------
|
|
458
|
+
str
|
|
459
|
+
The updated command string
|
|
460
|
+
"""
|
|
461
|
+
if self.light_source_setup == "variable":
|
|
462
|
+
command += f" -x {self.light_emission_config['x_pos']['default'].to(u.cm).value}"
|
|
463
|
+
command += f" -y {self.light_emission_config['y_pos']['default'].to(u.cm).value}"
|
|
464
|
+
command += f" -z {self.light_emission_config['z_pos']['default'].to(u.cm).value}"
|
|
465
|
+
command += (
|
|
466
|
+
f" -d {','.join(map(str, self.light_emission_config['direction']['default']))}"
|
|
467
|
+
)
|
|
468
|
+
command += f" -n {self.photons_per_run}"
|
|
469
|
+
|
|
470
|
+
elif self.light_source_setup == "layout":
|
|
471
|
+
x_cal, y_cal, z_cal = self._calibration_model.get_parameter_value_with_unit(
|
|
472
|
+
"array_element_position_ground"
|
|
473
|
+
)
|
|
474
|
+
command += f" -x {x_cal.to(u.cm).value}"
|
|
475
|
+
command += f" -y {y_cal.to(u.cm).value}"
|
|
476
|
+
command += f" -z {z_cal.to(u.cm).value}"
|
|
477
|
+
pointing_vector = self.calibration_pointing_direction()[0]
|
|
478
|
+
command += f" -d {','.join(map(str, pointing_vector))}"
|
|
479
|
+
|
|
480
|
+
command += f" -n {self.photons_per_run}"
|
|
481
|
+
self._logger.info(f"Photons per run: {self.photons_per_run} ")
|
|
482
|
+
|
|
483
|
+
laser_wavelength = self._calibration_model.get_parameter_value_with_unit(
|
|
484
|
+
"laser_wavelength"
|
|
485
|
+
)
|
|
486
|
+
command += f" -s {int(laser_wavelength.to(u.nm).value)}"
|
|
487
|
+
|
|
488
|
+
led_pulse_sigtime = self._calibration_model.get_parameter_value_with_unit(
|
|
489
|
+
"led_pulse_sigtime"
|
|
490
|
+
)
|
|
491
|
+
command += f" -p Gauss:{led_pulse_sigtime.to(u.ns).value}"
|
|
492
|
+
command += " -a isotropic"
|
|
281
493
|
|
|
282
494
|
return command
|
|
283
495
|
|
|
@@ -290,17 +502,22 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
290
502
|
str
|
|
291
503
|
The command to run sim_telarray
|
|
292
504
|
"""
|
|
293
|
-
#
|
|
294
|
-
|
|
505
|
+
# For flasher sims, avoid calibration pointing entirely; default angles to (0,0)
|
|
506
|
+
if self.light_source_type == "flasher":
|
|
507
|
+
angles = [0, 0]
|
|
508
|
+
else:
|
|
509
|
+
_, angles = self.calibration_pointing_direction()
|
|
295
510
|
|
|
296
|
-
|
|
297
|
-
command
|
|
298
|
-
command
|
|
299
|
-
command += f"
|
|
511
|
+
simtel_bin = self._simtel_path.joinpath("sim_telarray/bin/sim_telarray/")
|
|
512
|
+
# Build command without prefix; caller will add SIM_TELARRAY_CONFIG_PATH once
|
|
513
|
+
command = f"{simtel_bin} "
|
|
514
|
+
command += f"-I{self._telescope_model.config_file_directory} "
|
|
515
|
+
command += f"-I{simtel_bin} "
|
|
516
|
+
command += f"-c {self._telescope_model.config_file_path} "
|
|
300
517
|
self._remove_line_from_config(self._telescope_model.config_file_path, "array_triggers")
|
|
301
518
|
self._remove_line_from_config(self._telescope_model.config_file_path, "axes_offsets")
|
|
302
519
|
|
|
303
|
-
command += "
|
|
520
|
+
command += "-DNUM_TELESCOPES=1 "
|
|
304
521
|
|
|
305
522
|
command += super().get_config_option(
|
|
306
523
|
"altitude",
|
|
@@ -310,7 +527,7 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
310
527
|
)
|
|
311
528
|
command += super().get_config_option(
|
|
312
529
|
"atmospheric_transmission",
|
|
313
|
-
self.
|
|
530
|
+
self._site_model.get_parameter_value("atmospheric_transmission"),
|
|
314
531
|
)
|
|
315
532
|
command += super().get_config_option("TRIGGER_TELESCOPES", "1")
|
|
316
533
|
|
|
@@ -318,25 +535,38 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
318
535
|
command += super().get_config_option("PULSE_ANALYSIS", "-30")
|
|
319
536
|
command += super().get_config_option("MAXIMUM_TELESCOPES", 1)
|
|
320
537
|
|
|
321
|
-
if self.
|
|
538
|
+
if self.light_source_type == "variable":
|
|
322
539
|
command += super().get_config_option("telescope_theta", 0)
|
|
323
540
|
command += super().get_config_option("telescope_phi", 0)
|
|
324
541
|
else:
|
|
325
542
|
command += super().get_config_option("telescope_theta", f"{angles[0]}")
|
|
326
543
|
command += super().get_config_option("telescope_phi", f"{angles[1]}")
|
|
327
544
|
|
|
545
|
+
# For flasher runs, bypass reflections on primary mirror
|
|
546
|
+
if self.light_source_type == "flasher":
|
|
547
|
+
command += super().get_config_option("Bypass_Optics", "1")
|
|
548
|
+
|
|
328
549
|
command += super().get_config_option("power_law", "2.68")
|
|
550
|
+
app_name, app_mode = self._infer_application()
|
|
551
|
+
pref = self._get_prefix()
|
|
329
552
|
command += super().get_config_option(
|
|
330
|
-
"input_file", f"{self.output_directory}/{
|
|
553
|
+
"input_file", f"{self.output_directory}/{app_name}.iact.gz"
|
|
331
554
|
)
|
|
555
|
+
dist_suffix = ""
|
|
556
|
+
if self.light_source_setup == "variable":
|
|
557
|
+
try:
|
|
558
|
+
dist_val = int(self._get_distance_for_plotting().to_value(u.m))
|
|
559
|
+
dist_suffix = f"_d_{dist_val}"
|
|
560
|
+
except Exception: # pylint:disable=broad-except
|
|
561
|
+
dist_suffix = ""
|
|
562
|
+
|
|
332
563
|
command += super().get_config_option(
|
|
333
564
|
"output_file",
|
|
334
|
-
f"{self.output_directory}/{
|
|
565
|
+
f"{self.output_directory}/{pref}{app_name}_{app_mode}{dist_suffix}.simtel.zst",
|
|
335
566
|
)
|
|
336
567
|
command += super().get_config_option(
|
|
337
568
|
"histogram_file",
|
|
338
|
-
f"{self.output_directory}/"
|
|
339
|
-
f"{self.le_application[0]}_{self.le_application[1]}.ctsim.hdata\n",
|
|
569
|
+
f"{self.output_directory}/{pref}{app_name}_{app_mode}{dist_suffix}.ctsim.hdata\n",
|
|
340
570
|
)
|
|
341
571
|
|
|
342
572
|
# Remove the default sim_telarray configuration directories
|
|
@@ -362,65 +592,10 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
362
592
|
if not line.startswith(line_prefix):
|
|
363
593
|
file.write(line)
|
|
364
594
|
|
|
365
|
-
def
|
|
366
|
-
"""
|
|
367
|
-
Write out post-script file using read_cta in hessioxxx/bin/read_cta.
|
|
368
|
-
|
|
369
|
-
parts from the documentation
|
|
370
|
-
-r level (Use 10/5 tail-cut image cleaning and redo reconstruction.)
|
|
371
|
-
level >= 1: show parameters from sim_hessarray.
|
|
372
|
-
level >= 2: redo shower reconstruction
|
|
373
|
-
level >= 3: redo image cleaning (and shower reconstruction
|
|
374
|
-
with new image parameters)
|
|
375
|
-
level >= 4: redo amplitude summation
|
|
376
|
-
level >= 5: PostScript file includes original and
|
|
377
|
-
new shower reconstruction.
|
|
378
|
-
--integration-window w,o[,ps] *(Set integration window width and offset.)
|
|
379
|
-
For some integration schemes there is a pulse shaping option.
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
Returns
|
|
383
|
-
-------
|
|
384
|
-
str
|
|
385
|
-
Command to create the postscript file
|
|
386
|
-
"""
|
|
387
|
-
postscript_dir = self.output_directory.joinpath("postscripts")
|
|
388
|
-
postscript_dir.mkdir(parents=True, exist_ok=True)
|
|
389
|
-
|
|
390
|
-
command = str(self._simtel_path.joinpath("hessioxxx/bin/read_cta"))
|
|
391
|
-
command += " --min-tel 1 --min-trg-tel 1"
|
|
392
|
-
command += " -q --integration-scheme 4"
|
|
393
|
-
command += " --integration-window "
|
|
394
|
-
command += f"{kwargs['integration_window'][0]},{kwargs['integration_window'][1]}"
|
|
395
|
-
command += f" -r {kwargs['level']}"
|
|
396
|
-
command += " --plot-with-sum-only"
|
|
397
|
-
command += " --plot-with-pixel-amp --plot-with-pixel-id"
|
|
398
|
-
command += (
|
|
399
|
-
f" -p {postscript_dir}/"
|
|
400
|
-
f"{self.le_application[0]}_{self.le_application[1]}_"
|
|
401
|
-
f"d_{int(self.distance.to(u.m).value)}.ps"
|
|
402
|
-
)
|
|
403
|
-
command += (
|
|
404
|
-
f" {self.output_directory}/"
|
|
405
|
-
f"{self.le_application[0]}_{self.le_application[1]}.simtel.gz\n"
|
|
406
|
-
)
|
|
407
|
-
# ps2pdf required, now only store postscripts
|
|
408
|
-
# command += f"ps2pdf {self.output_directory}/{self.le_application}.ps
|
|
409
|
-
# {self.output_directory}/{self.le_application}.pdf"
|
|
410
|
-
return command
|
|
411
|
-
|
|
412
|
-
def prepare_script(self, generate_postscript=False, **kwargs):
|
|
595
|
+
def prepare_script(self):
|
|
413
596
|
"""
|
|
414
597
|
Build and return bash run script containing the light-emission command.
|
|
415
598
|
|
|
416
|
-
Parameters
|
|
417
|
-
----------
|
|
418
|
-
plot: bool
|
|
419
|
-
If output should be plotted.
|
|
420
|
-
|
|
421
|
-
generate_postscript: bool
|
|
422
|
-
If postscript should be generated with read_cta.
|
|
423
|
-
|
|
424
599
|
Returns
|
|
425
600
|
-------
|
|
426
601
|
Path
|
|
@@ -430,97 +605,98 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
430
605
|
|
|
431
606
|
_script_dir = self.output_directory.joinpath("scripts")
|
|
432
607
|
_script_dir.mkdir(parents=True, exist_ok=True)
|
|
433
|
-
_script_file = _script_dir.joinpath(f"{self.
|
|
608
|
+
_script_file = _script_dir.joinpath(f"{self._infer_application()[0]}-lightemission.sh")
|
|
434
609
|
self._logger.debug(f"Run bash script - {_script_file}")
|
|
435
610
|
|
|
611
|
+
target_out = Path(self._get_simulation_output_filename())
|
|
612
|
+
if target_out.exists():
|
|
613
|
+
msg = f"Simtel output file exists already, cancelling simulation: {target_out}"
|
|
614
|
+
self._logger.error(msg)
|
|
615
|
+
raise FileExistsError(msg)
|
|
616
|
+
|
|
436
617
|
command_le = self._make_light_emission_script()
|
|
437
618
|
command_simtel = self._make_simtel_script()
|
|
438
619
|
|
|
439
620
|
with _script_file.open("w", encoding="utf-8") as file:
|
|
440
|
-
file.write("#!/usr/bin/env bash\n
|
|
621
|
+
file.write("#!/usr/bin/env bash\n")
|
|
441
622
|
|
|
442
623
|
file.write(f"{command_le}\n\n")
|
|
624
|
+
app_name, _ = self._infer_application()
|
|
625
|
+
file.write(
|
|
626
|
+
f"[ -s '{self.output_directory}/{app_name}.iact.gz' ] || "
|
|
627
|
+
f"{{ echo 'LightEmission did not produce IACT file' >&2; exit 1; }}\n\n"
|
|
628
|
+
)
|
|
443
629
|
file.write(f"{command_simtel}\n\n")
|
|
444
630
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
command_plot = self._create_postscript(**kwargs)
|
|
448
|
-
file.write("# Generate postscript\n\n")
|
|
449
|
-
file.write(f"{command_plot}\n\n")
|
|
450
|
-
file.write("# End\n\n")
|
|
631
|
+
# Cleanup intermediate IACT file at the end of the run
|
|
632
|
+
file.write(f"rm -f '{self.output_directory}/{app_name}.iact.gz'\n\n")
|
|
451
633
|
|
|
452
634
|
_script_file.chmod(_script_file.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP)
|
|
453
635
|
return _script_file
|
|
454
636
|
|
|
455
|
-
def process_simulation_output(self, args_dict, figures):
|
|
456
|
-
"""Process the simulation output, including plotting and saving figures."""
|
|
457
|
-
try:
|
|
458
|
-
filename = self._get_simulation_output_filename()
|
|
459
|
-
distance = self._get_distance_for_plotting()
|
|
460
|
-
|
|
461
|
-
fig = self._plot_simulation_output(
|
|
462
|
-
filename,
|
|
463
|
-
args_dict["boundary_thresh"],
|
|
464
|
-
args_dict["picture_thresh"],
|
|
465
|
-
args_dict["min_neighbors"],
|
|
466
|
-
distance,
|
|
467
|
-
args_dict["return_cleaned"],
|
|
468
|
-
)
|
|
469
|
-
figures.append(fig)
|
|
470
|
-
|
|
471
|
-
except AttributeError:
|
|
472
|
-
msg = (
|
|
473
|
-
f"Telescope not triggered at distance of "
|
|
474
|
-
f"{self.light_emission_config['z_pos']['default']}"
|
|
475
|
-
)
|
|
476
|
-
self._logger.warning(msg)
|
|
477
|
-
|
|
478
637
|
def _get_simulation_output_filename(self):
|
|
479
638
|
"""Get the filename of the simulation output."""
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
639
|
+
dist_suffix = ""
|
|
640
|
+
if self.light_source_setup == "variable":
|
|
641
|
+
try:
|
|
642
|
+
dist_val = int(self._get_distance_for_plotting().to_value(u.m))
|
|
643
|
+
dist_suffix = f"_d_{dist_val}"
|
|
644
|
+
except Exception: # pylint:disable=broad-except
|
|
645
|
+
dist_suffix = ""
|
|
646
|
+
app_name, app_mode = self._infer_application()
|
|
647
|
+
pref = self._get_prefix()
|
|
648
|
+
return f"{self.output_directory}/{pref}{app_name}_{app_mode}{dist_suffix}.simtel.zst"
|
|
483
649
|
|
|
484
650
|
def _get_distance_for_plotting(self):
|
|
485
|
-
"""Get the distance to be used for plotting.
|
|
486
|
-
try:
|
|
487
|
-
return self.light_emission_config["z_pos"]["default"]
|
|
488
|
-
except KeyError:
|
|
489
|
-
return round(self.distance, 2)
|
|
490
|
-
|
|
491
|
-
def _plot_simulation_output(
|
|
492
|
-
self, filename, boundary_thresh, picture_thresh, min_neighbors, distance, return_cleaned
|
|
493
|
-
):
|
|
494
|
-
"""Plot the simulation output."""
|
|
495
|
-
return plot_simtel_ctapipe(
|
|
496
|
-
filename,
|
|
497
|
-
cleaning_args=[boundary_thresh, picture_thresh, min_neighbors],
|
|
498
|
-
distance=distance,
|
|
499
|
-
return_cleaned=return_cleaned,
|
|
500
|
-
)
|
|
501
|
-
|
|
502
|
-
def save_figures_to_pdf(self, figures, telescope):
|
|
503
|
-
"""Save the generated figures to a PDF file."""
|
|
504
|
-
save_figs_to_pdf(
|
|
505
|
-
figures,
|
|
506
|
-
f"{self.output_directory}/"
|
|
507
|
-
f"{telescope}_{self.le_application[0]}_{self.le_application[1]}.pdf",
|
|
508
|
-
)
|
|
651
|
+
"""Get the distance to be used for plotting as an astropy Quantity.
|
|
509
652
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
653
|
+
For flasher runs, use the flasher_depth (cm) from the flasher model.
|
|
654
|
+
For illuminator runs, use the configured z_pos quantity.
|
|
655
|
+
Otherwise, fall back to self.distance if set, or 0 m.
|
|
656
|
+
"""
|
|
657
|
+
if self.light_source_type == "flasher" and self._flasher_model is not None:
|
|
658
|
+
return self._flasher_model.get_parameter_value_with_unit("flasher_depth").to(u.m)
|
|
659
|
+
|
|
660
|
+
def _as_meters(val):
|
|
661
|
+
if isinstance(val, u.Quantity):
|
|
662
|
+
return val.to(u.m)
|
|
663
|
+
try:
|
|
664
|
+
return float(val) * u.m
|
|
665
|
+
except (TypeError, ValueError):
|
|
666
|
+
return None
|
|
667
|
+
|
|
668
|
+
cfg = self.light_emission_config or {}
|
|
669
|
+
z = cfg.get("z_pos")
|
|
670
|
+
if isinstance(z, dict):
|
|
671
|
+
z_def = z.get("default")
|
|
672
|
+
z_val = z_def[0] if isinstance(z_def, list | tuple) and z_def else z_def
|
|
673
|
+
z_q = _as_meters(z_val)
|
|
674
|
+
if z_q is not None:
|
|
675
|
+
return z_q
|
|
676
|
+
|
|
677
|
+
d_q = _as_meters(getattr(self, "distance", None))
|
|
678
|
+
if d_q is not None:
|
|
679
|
+
return d_q
|
|
680
|
+
|
|
681
|
+
return 0 * u.m
|
|
682
|
+
|
|
683
|
+
def run_simulation(self) -> Path:
|
|
684
|
+
"""Run the light emission simulation and return the output simtel file path."""
|
|
685
|
+
run_script = self.prepare_script()
|
|
686
|
+
log_path = Path(self.output_directory) / "logfile.log"
|
|
687
|
+
with open(log_path, "w", encoding="utf-8") as fh:
|
|
515
688
|
subprocess.run(
|
|
516
689
|
run_script,
|
|
517
690
|
shell=False,
|
|
518
691
|
check=False,
|
|
519
692
|
text=True,
|
|
520
|
-
stdout=
|
|
521
|
-
stderr=
|
|
693
|
+
stdout=fh,
|
|
694
|
+
stderr=fh,
|
|
522
695
|
)
|
|
523
|
-
self.
|
|
696
|
+
out = Path(self._get_simulation_output_filename())
|
|
697
|
+
if not out.exists():
|
|
698
|
+
self._logger.warning(f"Expected simtel output not found: {out}")
|
|
699
|
+
return out
|
|
524
700
|
|
|
525
701
|
def distance_list(self, arg):
|
|
526
702
|
"""
|
|
@@ -558,15 +734,8 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
558
734
|
raise KeyError(f"Key '{key}' not found in light emission configuration.")
|
|
559
735
|
|
|
560
736
|
def calculate_distance_telescope_calibration_device(self):
|
|
561
|
-
"""
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
Returns
|
|
565
|
-
-------
|
|
566
|
-
list of astropy.Quantity
|
|
567
|
-
A list of distances for variable positions or a single distance for layout positions.
|
|
568
|
-
"""
|
|
569
|
-
if not self.light_emission_config:
|
|
737
|
+
"""Calculate distance(s) between telescope and calibration device."""
|
|
738
|
+
if self.light_source_setup == "layout":
|
|
570
739
|
# Layout positions: Use DB coordinates
|
|
571
740
|
x_cal, y_cal, z_cal = self._calibration_model.get_parameter_value_with_unit(
|
|
572
741
|
"array_element_position_ground"
|
|
@@ -579,7 +748,7 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
579
748
|
tel_vect = np.array([x_tel, y_tel, z_tel])
|
|
580
749
|
cal_vect = np.array([x_cal, y_cal, z_cal])
|
|
581
750
|
distance = np.linalg.norm(cal_vect - tel_vect)
|
|
582
|
-
|
|
751
|
+
self._logger.info(f"Distance between telescope and calibration device: {distance} m")
|
|
583
752
|
return [distance * u.m]
|
|
584
753
|
|
|
585
754
|
# Variable positions: Calculate distances for all positions
|
|
@@ -595,7 +764,7 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
595
764
|
return distances
|
|
596
765
|
|
|
597
766
|
def simulate_variable_distances(self, args_dict):
|
|
598
|
-
"""Simulate light emission for variable distances."""
|
|
767
|
+
"""Simulate light emission for variable distances and return output files list."""
|
|
599
768
|
if args_dict["distances_ls"] is not None:
|
|
600
769
|
self.update_light_emission_config(
|
|
601
770
|
"z_pos", self.distance_list(args_dict["distances_ls"])
|
|
@@ -603,8 +772,7 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
603
772
|
self._logger.info(
|
|
604
773
|
f"Simulating for distances: {self.light_emission_config['z_pos']['default']}"
|
|
605
774
|
)
|
|
606
|
-
|
|
607
|
-
figures = []
|
|
775
|
+
outputs: list[Path] = []
|
|
608
776
|
distances = self.calculate_distance_telescope_calibration_device()
|
|
609
777
|
|
|
610
778
|
for current_distance, z_pos in zip(
|
|
@@ -612,15 +780,13 @@ class SimulatorLightEmission(SimtelRunner):
|
|
|
612
780
|
):
|
|
613
781
|
self.update_light_emission_config("z_pos", z_pos)
|
|
614
782
|
self.distance = current_distance
|
|
615
|
-
self.run_simulation(
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
self.distance = self.calculate_distance_telescope_calibration_device()[
|
|
623
|
-
|
|
624
|
-
]
|
|
625
|
-
self.run_simulation(args_dict, figures)
|
|
626
|
-
self.save_figures_to_pdf(figures, args_dict["telescope"])
|
|
783
|
+
outputs.append(self.run_simulation())
|
|
784
|
+
return outputs
|
|
785
|
+
|
|
786
|
+
def simulate_layout_positions(self, args_dict): # pylint: disable=unused-argument
|
|
787
|
+
"""Simulate light emission for layout positions and return output files list."""
|
|
788
|
+
# args_dict kept for API symmetry; explicitly mark as unused
|
|
789
|
+
del args_dict
|
|
790
|
+
self.distance = self.calculate_distance_telescope_calibration_device()[0]
|
|
791
|
+
# Single distance for layout
|
|
792
|
+
return [self.run_simulation()]
|