gammasimtools 0.18.0__py3-none-any.whl → 0.19.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.19.0.dist-info}/METADATA +26 -69
- gammasimtools-0.19.0.dist-info/RECORD +393 -0
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.19.0.dist-info}/entry_points.txt +9 -2
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.19.0.dist-info}/licenses/LICENSE +1 -1
- simtools/_version.py +16 -3
- simtools/applications/calculate_trigger_rate.py +1 -1
- 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_value_from_json_to_db.py +2 -1
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +8 -13
- simtools/applications/db_generate_compound_indexes.py +61 -0
- simtools/applications/db_get_file_from_db.py +1 -1
- 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/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_sim_telarray_histograms.py +1 -1
- 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 +379 -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 +2 -1
- 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 +29 -0
- 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 +34 -9
- simtools/db/db_handler.py +43 -37
- simtools/db/db_model_upload.py +3 -3
- simtools/dependencies.py +88 -25
- 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 +14 -7
- simtools/model/array_model.py +23 -4
- simtools/model/flasher_model.py +106 -0
- simtools/model/model_parameter.py +4 -4
- simtools/model/model_repository.py +197 -2
- simtools/model/telescope_model.py +3 -1
- simtools/production_configuration/derive_corsika_limits.py +361 -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/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 +2 -2
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +2 -2
- simtools/simtel/simtel_config_reader.py +2 -2
- simtools/simtel/simtel_config_writer.py +16 -4
- simtools/simtel/simtel_io_event_histograms.py +746 -0
- simtools/simtel/simtel_io_event_reader.py +15 -42
- simtools/simtel/simtel_io_event_writer.py +9 -9
- simtools/simtel/simtel_io_histogram.py +3 -1
- simtools/simtel/simtel_io_histograms.py +7 -3
- simtools/simtel/simtel_table_reader.py +92 -10
- 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/testing/configuration.py +24 -26
- simtools/testing/helpers.py +2 -2
- simtools/testing/log_inspector.py +50 -0
- simtools/testing/validate_output.py +87 -37
- simtools/utils/general.py +125 -255
- simtools/utils/geometry.py +36 -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_pixels.py +1 -1
- simtools/visualization/plot_tables.py +133 -37
- simtools/visualization/simtel_event_plots.py +816 -0
- simtools/visualization/visualize.py +4 -101
- gammasimtools-0.18.0.dist-info/RECORD +0 -376
- simtools/production_configuration/derive_corsika_limits_grid.py +0 -232
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.19.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.19.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
|
@@ -13,7 +13,7 @@ import matplotlib.pyplot as plt
|
|
|
13
13
|
import numpy as np
|
|
14
14
|
from astropy.table import QTable
|
|
15
15
|
|
|
16
|
-
from simtools.
|
|
16
|
+
from simtools.io import io_handler
|
|
17
17
|
from simtools.model.model_utils import compute_telescope_transmission
|
|
18
18
|
from simtools.ray_tracing.psf_analysis import PSFImage
|
|
19
19
|
from simtools.simtel.simulator_ray_tracing import SimulatorRayTracing
|
|
@@ -49,6 +49,8 @@ class RayTracing:
|
|
|
49
49
|
Single mirror mode flag.
|
|
50
50
|
use_random_focal_length: bool
|
|
51
51
|
Use random focal length flag.
|
|
52
|
+
random_focal_length_seed: int
|
|
53
|
+
Seed for the random number generator used for focal length variation.
|
|
52
54
|
mirror_numbers: list, str
|
|
53
55
|
List of mirror numbers (or 'all').
|
|
54
56
|
"""
|
|
@@ -71,6 +73,7 @@ class RayTracing:
|
|
|
71
73
|
source_distance=10.0 * u.km,
|
|
72
74
|
single_mirror_mode=False,
|
|
73
75
|
use_random_focal_length=False,
|
|
76
|
+
random_focal_length_seed=None,
|
|
74
77
|
mirror_numbers="all",
|
|
75
78
|
):
|
|
76
79
|
"""Initialize RayTracing class."""
|
|
@@ -87,6 +90,7 @@ class RayTracing:
|
|
|
87
90
|
self.off_axis_angle = np.around(off_axis_angle.to("deg").value, 5)
|
|
88
91
|
self.single_mirror_mode = single_mirror_mode
|
|
89
92
|
self.use_random_focal_length = use_random_focal_length
|
|
93
|
+
self.random_focal_length_seed = random_focal_length_seed
|
|
90
94
|
self.mirrors = self._initialize_mirror_configuration(source_distance, mirror_numbers)
|
|
91
95
|
self.output_directory = self._io_handler.get_output_directory(
|
|
92
96
|
label=self.label, sub_dir="ray_tracing"
|
|
@@ -185,7 +189,7 @@ class RayTracing:
|
|
|
185
189
|
"""
|
|
186
190
|
_focal_length = self.telescope_model.get_parameter_value("mirror_focal_length")
|
|
187
191
|
if self.use_random_focal_length:
|
|
188
|
-
rng = np.random.default_rng()
|
|
192
|
+
rng = np.random.default_rng(self.random_focal_length_seed)
|
|
189
193
|
_random_focal_length = self.telescope_model.get_parameter_value("random_focal_length")
|
|
190
194
|
if _random_focal_length[0] > 0.0:
|
|
191
195
|
_focal_length += rng.normal(loc=0, scale=_random_focal_length[0])
|
|
@@ -9,14 +9,14 @@ from collections import defaultdict
|
|
|
9
9
|
from itertools import groupby
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
|
+
import matplotlib.pyplot as plt
|
|
12
13
|
import numpy as np
|
|
13
14
|
|
|
14
15
|
from simtools.db import db_handler
|
|
15
|
-
from simtools.
|
|
16
|
+
from simtools.io import ascii_handler, io_handler
|
|
16
17
|
from simtools.model.telescope_model import TelescopeModel
|
|
17
|
-
from simtools.utils import general as gen
|
|
18
18
|
from simtools.utils import names
|
|
19
|
-
from simtools.visualization import plot_pixels
|
|
19
|
+
from simtools.visualization import plot_pixels, plot_tables
|
|
20
20
|
|
|
21
21
|
logger = logging.getLogger()
|
|
22
22
|
|
|
@@ -64,72 +64,141 @@ class ReadParameters:
|
|
|
64
64
|
)
|
|
65
65
|
self._model_version = model_version
|
|
66
66
|
|
|
67
|
-
def
|
|
67
|
+
def _generate_plots(self, parameter, parameter_version, input_file, outpath, design_type):
|
|
68
|
+
"""Generate plots based on the parameter type."""
|
|
69
|
+
plot_names = []
|
|
70
|
+
|
|
71
|
+
if parameter == "camera_config_file":
|
|
72
|
+
plot_names = self._plot_camera_config(parameter, parameter_version, input_file, outpath)
|
|
73
|
+
elif parameter_version:
|
|
74
|
+
plot_names = self._plot_parameter_tables(
|
|
75
|
+
parameter, parameter_version, outpath, design_type
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
return plot_names
|
|
79
|
+
|
|
80
|
+
def _plot_camera_config(self, parameter, parameter_version, input_file, outpath):
|
|
81
|
+
"""Generate plots for camera configuration files."""
|
|
82
|
+
if not parameter_version:
|
|
83
|
+
return []
|
|
84
|
+
|
|
85
|
+
plot_names = []
|
|
86
|
+
plot_name = input_file.stem.replace(".", "-")
|
|
87
|
+
plot_path = Path(f"{outpath}/{plot_name}").with_suffix(".png")
|
|
88
|
+
|
|
89
|
+
if not plot_path.exists():
|
|
90
|
+
plot_config = {
|
|
91
|
+
"file_name": input_file.name,
|
|
92
|
+
"telescope": self.array_element,
|
|
93
|
+
"parameter_version": parameter_version,
|
|
94
|
+
"site": self.site,
|
|
95
|
+
"model_version": self.model_version,
|
|
96
|
+
"parameter": parameter,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
plot_pixels.plot(
|
|
100
|
+
config=plot_config,
|
|
101
|
+
output_file=Path(f"{outpath}/{plot_name}"),
|
|
102
|
+
db_config=self.db_config,
|
|
103
|
+
)
|
|
104
|
+
plot_names.append(plot_name)
|
|
105
|
+
else:
|
|
106
|
+
logger.info(
|
|
107
|
+
"Camera configuration file plot already exists: %s",
|
|
108
|
+
plot_path,
|
|
109
|
+
)
|
|
110
|
+
plot_names.append(plot_name)
|
|
111
|
+
|
|
112
|
+
return plot_names
|
|
113
|
+
|
|
114
|
+
def _plot_parameter_tables(self, parameter, parameter_version, outpath, design_type):
|
|
115
|
+
"""Generate plots for parameter tables."""
|
|
116
|
+
telescope_design = self.db.get_design_model(
|
|
117
|
+
self.model_version, self.array_element, collection="telescopes"
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
if not self.array_element:
|
|
121
|
+
tel = None
|
|
122
|
+
elif not design_type:
|
|
123
|
+
tel = telescope_design
|
|
124
|
+
else:
|
|
125
|
+
tel = self.array_element
|
|
126
|
+
|
|
127
|
+
config_data = plot_tables.generate_plot_configurations(
|
|
128
|
+
parameter=parameter,
|
|
129
|
+
parameter_version=parameter_version,
|
|
130
|
+
site=self.site,
|
|
131
|
+
telescope=tel,
|
|
132
|
+
output_path=outpath,
|
|
133
|
+
plot_type="all",
|
|
134
|
+
db_config=self.db_config,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
if not config_data:
|
|
138
|
+
return []
|
|
139
|
+
|
|
140
|
+
plot_configs, output_files = config_data
|
|
141
|
+
plot_names = [i.stem for i in output_files]
|
|
142
|
+
|
|
143
|
+
for plot_config, output_file in zip(plot_configs, output_files):
|
|
144
|
+
image_output_file = outpath / output_file.name
|
|
145
|
+
if not image_output_file.with_suffix(".png").exists():
|
|
146
|
+
plot_tables.plot(
|
|
147
|
+
config=plot_config,
|
|
148
|
+
output_file=image_output_file,
|
|
149
|
+
db_config=self.db_config,
|
|
150
|
+
)
|
|
151
|
+
plt.close("all")
|
|
152
|
+
|
|
153
|
+
return plot_names
|
|
154
|
+
|
|
155
|
+
def _convert_to_md(self, parameter, parameter_version, input_file, design_type=False):
|
|
68
156
|
"""Convert a file to a Markdown file, preserving formatting."""
|
|
69
157
|
input_file = Path(input_file)
|
|
70
158
|
|
|
159
|
+
if not input_file.exists():
|
|
160
|
+
raise FileNotFoundError(f"Data file not found: {input_file}")
|
|
161
|
+
|
|
162
|
+
# Store the markdown output file path early and don't modify it
|
|
71
163
|
output_data_path = Path(self.output_path / "_data_files")
|
|
72
164
|
output_data_path.mkdir(parents=True, exist_ok=True)
|
|
73
165
|
output_file_name = Path(input_file.stem + ".md")
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
outpath = Path(io_handler.IOHandler().get_output_directory().parent / "_images")
|
|
77
|
-
outpath.mkdir(parents=True, exist_ok=True)
|
|
78
|
-
image_path = Path(f"{outpath}/{image_name}")
|
|
79
|
-
|
|
80
|
-
if parameter == "camera_config_file" and parameter_version:
|
|
81
|
-
image_path = Path(f"{outpath}/{input_file.stem.replace('.', '-')}")
|
|
82
|
-
if not (image_path.with_suffix(".png")).exists():
|
|
83
|
-
logger.info("Plotting camera configuration file: %s", input_file.name)
|
|
84
|
-
plot_config = {
|
|
85
|
-
"file_name": input_file.name,
|
|
86
|
-
"telescope": self.array_element,
|
|
87
|
-
"parameter_version": parameter_version,
|
|
88
|
-
"site": self.site,
|
|
89
|
-
"model_version": self.model_version,
|
|
90
|
-
"parameter": parameter,
|
|
91
|
-
}
|
|
166
|
+
relative_path = f"_data_files/{output_file_name}"
|
|
167
|
+
markdown_output_file = output_data_path / output_file_name
|
|
92
168
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
db_config=self.db_config,
|
|
97
|
-
)
|
|
98
|
-
else:
|
|
99
|
-
logger.info(
|
|
100
|
-
"Camera configuration file plot already exists: %s",
|
|
101
|
-
image_path.with_suffix(".png"),
|
|
102
|
-
)
|
|
169
|
+
if not markdown_output_file.exists():
|
|
170
|
+
outpath = Path(io_handler.IOHandler().get_output_directory().parent / "_images")
|
|
171
|
+
outpath.mkdir(parents=True, exist_ok=True)
|
|
103
172
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
outfile.write(
|
|
113
|
-
"\n\nThe full file can be found in the Simulation Model repository [here]"
|
|
114
|
-
"(https://gitlab.cta-observatory.org/cta-science/simulations/"
|
|
115
|
-
"simulation-model/simulation-models/-/blob/main/simulation-models/"
|
|
116
|
-
f"model_parameters/Files/{input_file.name}).\n\n"
|
|
117
|
-
)
|
|
118
|
-
outfile.write("\n\n")
|
|
119
|
-
outfile.write("The first 30 lines of the file are:\n")
|
|
120
|
-
outfile.write("```\n")
|
|
121
|
-
first_30_lines = "".join(file_contents[:30])
|
|
122
|
-
outfile.write(first_30_lines)
|
|
123
|
-
outfile.write("\n```")
|
|
173
|
+
plot_names = self._generate_plots(
|
|
174
|
+
parameter, parameter_version, input_file, outpath, design_type
|
|
175
|
+
)
|
|
176
|
+
# Write markdown file using the stored path
|
|
177
|
+
file_contents = ascii_handler.read_file_encoded_in_utf_or_latin(input_file)
|
|
178
|
+
|
|
179
|
+
with markdown_output_file.open("w", encoding="utf-8") as outfile:
|
|
180
|
+
outfile.write(f"# {input_file.stem}\n")
|
|
124
181
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
raise FileNotFoundError(f"Data file not found: {input_file}.") from exc
|
|
182
|
+
for plot_name in plot_names:
|
|
183
|
+
outfile.write(f"\n\n")
|
|
128
184
|
|
|
129
|
-
|
|
185
|
+
outfile.write(
|
|
186
|
+
"\n\nThe full file can be found in the Simulation Model repository [here]"
|
|
187
|
+
"(https://gitlab.cta-observatory.org/cta-science/simulations/"
|
|
188
|
+
"simulation-model/simulation-models/-/blob/main/simulation-models/"
|
|
189
|
+
f"model_parameters/Files/{input_file.name}).\n\n"
|
|
190
|
+
)
|
|
191
|
+
outfile.write("\n\n")
|
|
192
|
+
outfile.write("The first 30 lines of the file are:\n")
|
|
193
|
+
outfile.write("```\n")
|
|
194
|
+
first_30_lines = "".join(file_contents[:30])
|
|
195
|
+
outfile.write(first_30_lines)
|
|
196
|
+
outfile.write("\n```")
|
|
197
|
+
|
|
198
|
+
return relative_path
|
|
130
199
|
|
|
131
200
|
def _format_parameter_value(
|
|
132
|
-
self, parameter, value_data, unit, file_flag, parameter_version=None
|
|
201
|
+
self, parameter, value_data, unit, file_flag, parameter_version=None, design_type=False
|
|
133
202
|
):
|
|
134
203
|
"""Format parameter value based on type."""
|
|
135
204
|
if file_flag:
|
|
@@ -140,7 +209,9 @@ class ReadParameters:
|
|
|
140
209
|
"cta-science/simulations/simulation-model/simulation-models/-/blob/main/"
|
|
141
210
|
f"simulation-models/model_parameters/Files/{value_data})"
|
|
142
211
|
).strip()
|
|
143
|
-
output_file_name = self._convert_to_md(
|
|
212
|
+
output_file_name = self._convert_to_md(
|
|
213
|
+
parameter, parameter_version, input_file_name, design_type
|
|
214
|
+
)
|
|
144
215
|
return f"[{Path(value_data).name}]({output_file_name})".strip()
|
|
145
216
|
if isinstance(value_data, (str | int | float)):
|
|
146
217
|
return f"{value_data} {unit}".strip()
|
|
@@ -326,9 +397,10 @@ class ReadParameters:
|
|
|
326
397
|
if value_data is None:
|
|
327
398
|
continue
|
|
328
399
|
|
|
400
|
+
design_type = names.is_design_type(telescope_model.name)
|
|
329
401
|
file_flag = parameter_data.get("file", False)
|
|
330
402
|
value = self._format_parameter_value(
|
|
331
|
-
parameter, value_data, unit, file_flag, parameter_version
|
|
403
|
+
parameter, value_data, unit, file_flag, parameter_version, design_type
|
|
332
404
|
)
|
|
333
405
|
|
|
334
406
|
description = parameter_descriptions.get(parameter).get("description")
|
|
@@ -338,10 +410,10 @@ class ReadParameters:
|
|
|
338
410
|
inst_class = parameter_descriptions.get(parameter).get("inst_class")
|
|
339
411
|
|
|
340
412
|
matching_instrument = parameter_data["instrument"] == telescope_model.name
|
|
341
|
-
if not
|
|
413
|
+
if not design_type and matching_instrument:
|
|
342
414
|
parameter = f"***{parameter}***"
|
|
343
415
|
parameter_version = f"***{parameter_version}***"
|
|
344
|
-
if not
|
|
416
|
+
if not self.is_markdown_link(value):
|
|
345
417
|
value = f"***{value}***"
|
|
346
418
|
description = f"***{description}***"
|
|
347
419
|
short_description = f"***{short_description}***"
|
|
@@ -723,7 +795,7 @@ class ReadParameters:
|
|
|
723
795
|
if not names.is_design_type(array_element) and matching_instrument:
|
|
724
796
|
parameter = f"***{parameter}***"
|
|
725
797
|
parameter_version = f"***{parameter_version}***"
|
|
726
|
-
if not
|
|
798
|
+
if not self.is_markdown_link(value):
|
|
727
799
|
value = f"***{value}***"
|
|
728
800
|
description = f"***{description}***"
|
|
729
801
|
short_description = f"***{short_description}***"
|
|
@@ -750,6 +822,22 @@ class ReadParameters:
|
|
|
750
822
|
|
|
751
823
|
return data
|
|
752
824
|
|
|
825
|
+
def is_markdown_link(self, value):
|
|
826
|
+
"""
|
|
827
|
+
Return True if the string is a Markdown-style link: [text](target).
|
|
828
|
+
|
|
829
|
+
Parameters
|
|
830
|
+
----------
|
|
831
|
+
value : str
|
|
832
|
+
The string to check.
|
|
833
|
+
|
|
834
|
+
Returns
|
|
835
|
+
-------
|
|
836
|
+
bool
|
|
837
|
+
True if the string is a Markdown link, False otherwise.
|
|
838
|
+
"""
|
|
839
|
+
return bool(re.fullmatch(r"\[[^\]]*\]\([^)]+\)", value.strip()))
|
|
840
|
+
|
|
753
841
|
def produce_calibration_reports(self):
|
|
754
842
|
"""Write calibration reports."""
|
|
755
843
|
calibration_array_elements = self.db.get_array_elements(
|
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
import stat
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
|
-
from simtools.
|
|
7
|
+
from simtools.io import io_handler
|
|
8
8
|
from simtools.runners.runner_services import RunnerServices
|
|
9
9
|
|
|
10
10
|
__all__ = ["CorsikaRunner", "MissingRequiredEntryInCorsikaConfigError"]
|
|
@@ -43,6 +43,7 @@ class CorsikaSimtelRunner:
|
|
|
43
43
|
use_multipipe=False,
|
|
44
44
|
sim_telarray_seeds=None,
|
|
45
45
|
sequential=False,
|
|
46
|
+
calibration_runner_args=None,
|
|
46
47
|
):
|
|
47
48
|
self._logger = logging.getLogger(__name__)
|
|
48
49
|
self.corsika_config = (
|
|
@@ -55,6 +56,7 @@ class CorsikaSimtelRunner:
|
|
|
55
56
|
self.sim_telarray_seeds = sim_telarray_seeds
|
|
56
57
|
self.label = label
|
|
57
58
|
self.sequential = "--sequential" if sequential else ""
|
|
59
|
+
self.calibration_runner_args = calibration_runner_args
|
|
58
60
|
|
|
59
61
|
self.base_corsika_config.set_output_file_and_directory(use_multipipe)
|
|
60
62
|
self.corsika_runner = CorsikaRunner(
|
|
@@ -124,11 +126,18 @@ class CorsikaSimtelRunner:
|
|
|
124
126
|
|
|
125
127
|
with open(multipipe_file, "w", encoding="utf-8") as file:
|
|
126
128
|
for simulator_array in self.simulator_array:
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
if self.calibration_runner_args:
|
|
130
|
+
run_command = simulator_array.make_run_command_for_calibration_simulations(
|
|
131
|
+
run_number=run_number,
|
|
132
|
+
input_file="-", # instruct sim_telarray to take input from standard output
|
|
133
|
+
calibration_runner_args=self.calibration_runner_args,
|
|
134
|
+
)
|
|
135
|
+
else:
|
|
136
|
+
run_command = simulator_array.make_run_command(
|
|
137
|
+
run_number=run_number,
|
|
138
|
+
input_file="-", # instruct sim_telarray to take input from standard output
|
|
139
|
+
weak_pointing=self._determine_pointing_option(self.label),
|
|
140
|
+
)
|
|
132
141
|
file.write(f"{run_command}")
|
|
133
142
|
file.write("\n")
|
|
134
143
|
self._logger.info(f"Multipipe script: {multipipe_file}")
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
-
from simtools.
|
|
6
|
+
from simtools.io import io_handler
|
|
7
7
|
|
|
8
8
|
_logger = logging.getLogger(__name__)
|
|
9
9
|
|
|
@@ -139,11 +139,16 @@ class RunnerServices:
|
|
|
139
139
|
zenith = self.corsika_config.get_config_parameter("THETAP")[0]
|
|
140
140
|
azimuth = self.corsika_config.azimuth_angle
|
|
141
141
|
run_number_string = self._get_run_number_string(info_for_file_name["run_number"])
|
|
142
|
-
|
|
142
|
+
prefix = (
|
|
143
143
|
f"{info_for_file_name['primary']}_{run_number_string}_"
|
|
144
|
-
|
|
145
|
-
f"{
|
|
146
|
-
|
|
144
|
+
if info_for_file_name["primary"]
|
|
145
|
+
else f"{run_number_string}_"
|
|
146
|
+
)
|
|
147
|
+
return (
|
|
148
|
+
prefix
|
|
149
|
+
+ f"za{round(zenith):02}deg_azm{azimuth:03}deg_"
|
|
150
|
+
+ f"{info_for_file_name['site']}_{info_for_file_name['array_name']}_"
|
|
151
|
+
+ f"{info_for_file_name['model_version']}{file_label}"
|
|
147
152
|
)
|
|
148
153
|
|
|
149
154
|
def _get_log_file_path(self, file_type, file_name):
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"""Tools for running applications in the simtools framework."""
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import simtools.utils.general as gen
|
|
8
|
+
from simtools import dependencies
|
|
9
|
+
from simtools.io import ascii_handler
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def run_applications(args_dict, db_config, logger):
|
|
13
|
+
"""
|
|
14
|
+
Run simtools applications step-by-step as defined in a configuration file.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
args_dict : dict
|
|
19
|
+
Dictionary containing command line arguments.
|
|
20
|
+
db_config : dict
|
|
21
|
+
Database configuration
|
|
22
|
+
logger : logging.Logger
|
|
23
|
+
Logger for logging application output.
|
|
24
|
+
"""
|
|
25
|
+
configurations, runtime_environment, log_file = _read_application_configuration(
|
|
26
|
+
args_dict["configuration_file"], args_dict.get("steps"), logger
|
|
27
|
+
)
|
|
28
|
+
run_time = (
|
|
29
|
+
read_runtime_environment(runtime_environment)
|
|
30
|
+
if not args_dict["ignore_runtime_environment"]
|
|
31
|
+
else []
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
with log_file.open("w", encoding="utf-8") as file:
|
|
35
|
+
file.write("Running simtools applications\n")
|
|
36
|
+
file.write(dependencies.get_version_string(db_config, run_time))
|
|
37
|
+
|
|
38
|
+
for config in configurations:
|
|
39
|
+
app = config.get("application")
|
|
40
|
+
if not config.get("run_application"):
|
|
41
|
+
logger.info(f"Skipping application: {app}")
|
|
42
|
+
continue
|
|
43
|
+
logger.info(f"Running application: {app}")
|
|
44
|
+
stdout, stderr = run_application(run_time, app, config.get("configuration"), logger)
|
|
45
|
+
file.write("=" * 80 + "\n")
|
|
46
|
+
file.write(f"Application: {app}\nSTDOUT:\n{stdout}\nSTDERR:\n{stderr}\n")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def run_application(runtime_environment, application, configuration, logger):
|
|
50
|
+
"""
|
|
51
|
+
Run a simtools application and return stdout and stderr.
|
|
52
|
+
|
|
53
|
+
Allow to specify a runtime environment (e.g., Docker) and a working directory.
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
runtime_environment : list
|
|
58
|
+
Command to run the application in the specified runtime environment.
|
|
59
|
+
application : str
|
|
60
|
+
Name of the application to run.
|
|
61
|
+
configuration : dict
|
|
62
|
+
Configuration for the application.
|
|
63
|
+
logger : logging.Logger
|
|
64
|
+
Logger for logging application output.
|
|
65
|
+
|
|
66
|
+
Returns
|
|
67
|
+
-------
|
|
68
|
+
tuple
|
|
69
|
+
stdout and stderr from the application run.
|
|
70
|
+
|
|
71
|
+
"""
|
|
72
|
+
command = [application, *_convert_dict_to_args(configuration)]
|
|
73
|
+
if runtime_environment:
|
|
74
|
+
command = runtime_environment + command
|
|
75
|
+
try:
|
|
76
|
+
result = subprocess.run(
|
|
77
|
+
command,
|
|
78
|
+
check=True,
|
|
79
|
+
capture_output=True,
|
|
80
|
+
text=True,
|
|
81
|
+
)
|
|
82
|
+
except subprocess.CalledProcessError as exc:
|
|
83
|
+
logger.error(f"Error running application {application}: {exc.stderr}")
|
|
84
|
+
raise exc
|
|
85
|
+
|
|
86
|
+
return result.stdout, result.stderr
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _convert_dict_to_args(parameters):
|
|
90
|
+
"""
|
|
91
|
+
Convert a dictionary of parameters to a list of command line arguments.
|
|
92
|
+
|
|
93
|
+
Parameters
|
|
94
|
+
----------
|
|
95
|
+
parameters : dict
|
|
96
|
+
Dictionary containing parameters to convert.
|
|
97
|
+
|
|
98
|
+
Returns
|
|
99
|
+
-------
|
|
100
|
+
list
|
|
101
|
+
List of command line arguments.
|
|
102
|
+
"""
|
|
103
|
+
args = []
|
|
104
|
+
for key, value in parameters.items():
|
|
105
|
+
if isinstance(value, bool):
|
|
106
|
+
if value:
|
|
107
|
+
args.append(f"--{key}")
|
|
108
|
+
elif isinstance(value, list):
|
|
109
|
+
args.extend([f"--{key}", *(str(item) for item in value)])
|
|
110
|
+
else:
|
|
111
|
+
args.extend([f"--{key}", str(value)])
|
|
112
|
+
return args
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _read_application_configuration(configuration_file, steps, logger):
|
|
116
|
+
"""
|
|
117
|
+
Read application configuration from file and modify for setting workflows.
|
|
118
|
+
|
|
119
|
+
Strong assumptions on the structure of input and output files:
|
|
120
|
+
|
|
121
|
+
- configuration file is expected to be in './input/<workflow directory>/<yaml file>'
|
|
122
|
+
- output files will be written out to './output/<workflow directory>/'
|
|
123
|
+
|
|
124
|
+
Replaces the placeholders in the configuration file with the actual values.
|
|
125
|
+
Sets 'USE_PLAIN_OUTPUT_PATH' to True for all applications.
|
|
126
|
+
|
|
127
|
+
Parameters
|
|
128
|
+
----------
|
|
129
|
+
configuration_file : str
|
|
130
|
+
Configuration file name.
|
|
131
|
+
steps : list
|
|
132
|
+
List of steps to be executed (None: all steps).
|
|
133
|
+
logger : Logger
|
|
134
|
+
Logger object.
|
|
135
|
+
|
|
136
|
+
Returns
|
|
137
|
+
-------
|
|
138
|
+
dict
|
|
139
|
+
Application configuration.
|
|
140
|
+
dict:
|
|
141
|
+
Runtime environment configuration.
|
|
142
|
+
Path
|
|
143
|
+
Path to the log file.
|
|
144
|
+
|
|
145
|
+
"""
|
|
146
|
+
job_configuration = ascii_handler.collect_data_from_file(configuration_file)
|
|
147
|
+
configurations = job_configuration.get("applications")
|
|
148
|
+
output_path, setting_workflow = _set_input_output_directories(configuration_file)
|
|
149
|
+
logger.info(f"Setting workflow output path to {output_path}")
|
|
150
|
+
for step_count, config in enumerate(configurations, start=1):
|
|
151
|
+
config["run_application"] = step_count in steps if steps else True
|
|
152
|
+
config = gen.change_dict_keys_case(config, True)
|
|
153
|
+
config["configuration"] = _replace_placeholders_in_configuration(
|
|
154
|
+
config.get("configuration", {}),
|
|
155
|
+
output_path,
|
|
156
|
+
setting_workflow,
|
|
157
|
+
)
|
|
158
|
+
configurations[step_count - 1] = config
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
configurations,
|
|
162
|
+
job_configuration.get("runtime_environment"),
|
|
163
|
+
output_path / "simtools.log",
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _replace_placeholders_in_configuration(
|
|
168
|
+
configuration, output_path, setting_workflow, place_holder="__SETTING_WORKFLOW__"
|
|
169
|
+
):
|
|
170
|
+
"""
|
|
171
|
+
Replace placeholders in the configuration dictionary.
|
|
172
|
+
|
|
173
|
+
Parameters
|
|
174
|
+
----------
|
|
175
|
+
configuration : dict
|
|
176
|
+
Configuration dictionary.
|
|
177
|
+
output_path : Path
|
|
178
|
+
Path to the output directory.
|
|
179
|
+
setting_workflow : str
|
|
180
|
+
The setting workflow to replace the placeholder with.
|
|
181
|
+
place_holder : str
|
|
182
|
+
Placeholder to be replaced.
|
|
183
|
+
|
|
184
|
+
Returns
|
|
185
|
+
-------
|
|
186
|
+
dict
|
|
187
|
+
Configuration dictionary with placeholders replaced.
|
|
188
|
+
"""
|
|
189
|
+
for key, value in configuration.items():
|
|
190
|
+
if isinstance(value, str):
|
|
191
|
+
configuration[key] = value.replace(place_holder, setting_workflow)
|
|
192
|
+
if isinstance(value, list):
|
|
193
|
+
configuration[key] = [
|
|
194
|
+
item.replace(place_holder, setting_workflow) if isinstance(item, str) else item
|
|
195
|
+
for item in value
|
|
196
|
+
]
|
|
197
|
+
if output_path:
|
|
198
|
+
configuration["use_plain_output_path"] = True
|
|
199
|
+
configuration["output_path"] = str(output_path)
|
|
200
|
+
|
|
201
|
+
return configuration
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _set_input_output_directories(path):
|
|
205
|
+
"""
|
|
206
|
+
Set input and output directories based on the configuration file path.
|
|
207
|
+
|
|
208
|
+
Tuned to simulation models setting workflows.
|
|
209
|
+
|
|
210
|
+
Parameters
|
|
211
|
+
----------
|
|
212
|
+
path : str or Path
|
|
213
|
+
Path to the configuration file.
|
|
214
|
+
|
|
215
|
+
Returns
|
|
216
|
+
-------
|
|
217
|
+
tuple
|
|
218
|
+
The first part is the 'input' directory, the second part is the subdirectory name
|
|
219
|
+
"""
|
|
220
|
+
path = Path(path).resolve()
|
|
221
|
+
try:
|
|
222
|
+
input_index = path.parts.index("input")
|
|
223
|
+
# Get all parts after 'input', excluding the filename
|
|
224
|
+
subdirs = path.parts[input_index + 1 : -1]
|
|
225
|
+
setting_workflow = "/".join(subdirs)
|
|
226
|
+
workflow_dir = path.parts[input_index]
|
|
227
|
+
except (ValueError, IndexError) as exc:
|
|
228
|
+
raise ValueError(f"Could not find subdirectory under 'input': {exc}") from exc
|
|
229
|
+
|
|
230
|
+
output_path = Path(str(workflow_dir).replace("input", "output")) / Path(setting_workflow)
|
|
231
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
|
232
|
+
return output_path, "/".join(subdirs)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def read_runtime_environment(runtime_environment, workdir="/workdir/external/"):
|
|
236
|
+
"""
|
|
237
|
+
Read the runtime environment (e.g. docker runtime) and generate the required command.
|
|
238
|
+
|
|
239
|
+
Parameters
|
|
240
|
+
----------
|
|
241
|
+
runtime_environment : str or None
|
|
242
|
+
Path to the runtime environment configuration file.
|
|
243
|
+
|
|
244
|
+
Returns
|
|
245
|
+
-------
|
|
246
|
+
list
|
|
247
|
+
Runtime command.
|
|
248
|
+
"""
|
|
249
|
+
if runtime_environment is None:
|
|
250
|
+
return []
|
|
251
|
+
|
|
252
|
+
engine = runtime_environment.get("container_engine", "docker")
|
|
253
|
+
if shutil.which(engine) is None:
|
|
254
|
+
raise RuntimeError(f"Container engine '{engine}' not found.")
|
|
255
|
+
cmd = [engine, "run", "--rm", "-v", f"{Path.cwd()}:{workdir}", "-w", workdir]
|
|
256
|
+
|
|
257
|
+
if options := runtime_environment.get("options"):
|
|
258
|
+
for opt in options:
|
|
259
|
+
cmd.extend(opt.split())
|
|
260
|
+
|
|
261
|
+
if env := runtime_environment.get("env_file"):
|
|
262
|
+
cmd += ["--env-file", env]
|
|
263
|
+
if net := runtime_environment.get("network"):
|
|
264
|
+
cmd += ["--network", net]
|
|
265
|
+
|
|
266
|
+
cmd.append(runtime_environment["image"])
|
|
267
|
+
return cmd
|