gammasimtools 0.17.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.17.0.dist-info → gammasimtools-0.19.0.dist-info}/METADATA +27 -69
- gammasimtools-0.19.0.dist-info/RECORD +393 -0
- {gammasimtools-0.17.0.dist-info → gammasimtools-0.19.0.dist-info}/entry_points.txt +10 -2
- {gammasimtools-0.17.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_simulation_model_from_repository_to_db.py +10 -1
- 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 +18 -12
- 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 +97 -5
- 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 +16 -18
- simtools/applications/plot_array_layout.py +3 -3
- simtools/applications/plot_simtel_events.py +379 -0
- simtools/applications/plot_tabular_data.py +21 -3
- simtools/applications/plot_tabular_data_for_model_parameter.py +104 -0
- simtools/applications/print_version.py +8 -9
- simtools/applications/production_derive_corsika_limits.py +64 -27
- 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 +31 -1
- simtools/configuration/configurator.py +4 -4
- simtools/constants.py +2 -0
- 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 +88 -24
- simtools/data_model/validate_data.py +34 -9
- simtools/db/db_handler.py +48 -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/{io_operations/io_table_handler.py → io/table_handler.py} +1 -1
- simtools/job_execution/htcondor_script_generator.py +15 -4
- simtools/layout/array_layout.py +1 -1
- simtools/layout/array_layout_utils.py +19 -8
- simtools/model/array_model.py +28 -5
- 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/resources/array-element-ids.json +126 -0
- 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 +7 -3
- 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 +42 -1
- simtools/schemas/model_parameters/atmospheric_transmission.schema.yml +44 -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 +11 -1
- simtools/schemas/model_parameters/camera_filter_incidence_angle.schema.yml +11 -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 +32 -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 +13 -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 +11 -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 +11 -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 +13 -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 +20 -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 +11 -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 +51 -59
- 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 +16 -43
- simtools/simtel/simtel_io_event_writer.py +46 -10
- simtools/simtel/simtel_io_histogram.py +3 -1
- simtools/simtel/simtel_io_histograms.py +7 -3
- simtools/simtel/simtel_io_metadata.py +99 -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 -257
- simtools/utils/geometry.py +36 -0
- simtools/utils/names.py +72 -3
- simtools/visualization/legend_handlers.py +180 -264
- simtools/visualization/plot_array_layout.py +20 -8
- simtools/visualization/plot_pixels.py +1 -2
- simtools/visualization/plot_tables.py +202 -27
- simtools/visualization/simtel_event_plots.py +816 -0
- simtools/visualization/visualize.py +4 -101
- gammasimtools-0.17.0.dist-info/RECORD +0 -374
- simtools/production_configuration/derive_corsika_limits_grid.py +0 -189
- {gammasimtools-0.17.0.dist-info → gammasimtools-0.19.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.17.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/{schemas → resources}/array_elements.yml +0 -0
simtools/db/db_handler.py
CHANGED
|
@@ -13,9 +13,9 @@ from packaging.version import Version
|
|
|
13
13
|
from pymongo import MongoClient
|
|
14
14
|
|
|
15
15
|
from simtools.data_model import validate_data
|
|
16
|
-
from simtools.
|
|
16
|
+
from simtools.io import ascii_handler, io_handler
|
|
17
17
|
from simtools.simtel import simtel_table_reader
|
|
18
|
-
from simtools.utils import
|
|
18
|
+
from simtools.utils import names, value_conversion
|
|
19
19
|
|
|
20
20
|
__all__ = ["DatabaseHandler"]
|
|
21
21
|
|
|
@@ -81,6 +81,9 @@ class DatabaseHandler:
|
|
|
81
81
|
|
|
82
82
|
self._set_up_connection()
|
|
83
83
|
self._find_latest_simulation_model_db()
|
|
84
|
+
self.db_name = (
|
|
85
|
+
self.mongo_db_config.get("db_simulation_model", None) if self.mongo_db_config else None
|
|
86
|
+
)
|
|
84
87
|
|
|
85
88
|
def _set_up_connection(self):
|
|
86
89
|
"""Open the connection to MongoDB."""
|
|
@@ -179,6 +182,28 @@ class DatabaseHandler:
|
|
|
179
182
|
else:
|
|
180
183
|
raise ValueError("Found LATEST in the DB name but no matching versions found in DB.")
|
|
181
184
|
|
|
185
|
+
def generate_compound_indexes(self, db_name=None):
|
|
186
|
+
"""
|
|
187
|
+
Generate compound indexes for the MongoDB collections.
|
|
188
|
+
|
|
189
|
+
Indexes based on the typical query patterns.
|
|
190
|
+
"""
|
|
191
|
+
db_name = db_name or self.db_name
|
|
192
|
+
collection_names = [
|
|
193
|
+
"telescopes",
|
|
194
|
+
"sites",
|
|
195
|
+
"configuration_sim_telarray",
|
|
196
|
+
"configuration_corsika",
|
|
197
|
+
"calibration_devices",
|
|
198
|
+
]
|
|
199
|
+
for collection_name in collection_names:
|
|
200
|
+
db_collection = self.get_collection(collection_name, db_name=db_name)
|
|
201
|
+
db_collection.create_index(
|
|
202
|
+
[("instrument", 1), ("site", 1), ("parameter", 1), ("parameter_version", 1)]
|
|
203
|
+
)
|
|
204
|
+
db_collection = self.get_collection("production_tables", db_name=db_name)
|
|
205
|
+
db_collection.create_index([("collection", 1), ("model_version", 1)])
|
|
206
|
+
|
|
182
207
|
def get_model_parameter(
|
|
183
208
|
self,
|
|
184
209
|
parameter,
|
|
@@ -333,24 +358,23 @@ class DatabaseHandler:
|
|
|
333
358
|
)
|
|
334
359
|
return DatabaseHandler.model_parameters_cached[cache_key]
|
|
335
360
|
|
|
336
|
-
def get_collection(self,
|
|
361
|
+
def get_collection(self, collection_name, db_name=None):
|
|
337
362
|
"""
|
|
338
363
|
Get a collection from the DB.
|
|
339
364
|
|
|
340
365
|
Parameters
|
|
341
366
|
----------
|
|
342
|
-
db_name: str
|
|
343
|
-
Name of the DB.
|
|
344
367
|
collection_name: str
|
|
345
368
|
Name of the collection.
|
|
369
|
+
db_name: str
|
|
370
|
+
Name of the DB.
|
|
346
371
|
|
|
347
372
|
Returns
|
|
348
373
|
-------
|
|
349
374
|
pymongo.collection.Collection
|
|
350
375
|
The collection from the DB.
|
|
351
|
-
|
|
352
376
|
"""
|
|
353
|
-
db_name = self.
|
|
377
|
+
db_name = db_name or self.db_name
|
|
354
378
|
return DatabaseHandler.db_client[db_name][collection_name]
|
|
355
379
|
|
|
356
380
|
def get_collections(self, db_name=None, model_collections_only=False):
|
|
@@ -370,7 +394,7 @@ class DatabaseHandler:
|
|
|
370
394
|
List of collection names
|
|
371
395
|
|
|
372
396
|
"""
|
|
373
|
-
db_name = db_name or self.
|
|
397
|
+
db_name = db_name or self.db_name
|
|
374
398
|
if db_name not in self.list_of_collections:
|
|
375
399
|
self.list_of_collections[db_name] = DatabaseHandler.db_client[
|
|
376
400
|
db_name
|
|
@@ -409,6 +433,11 @@ class DatabaseHandler:
|
|
|
409
433
|
Version of the model.
|
|
410
434
|
export_file_as_table: bool
|
|
411
435
|
If True, export the file as an astropy table (ecsv format).
|
|
436
|
+
|
|
437
|
+
Returns
|
|
438
|
+
-------
|
|
439
|
+
astropy.table.Table or None
|
|
440
|
+
If export_file_as_table is True
|
|
412
441
|
"""
|
|
413
442
|
parameters = self.get_model_parameter(
|
|
414
443
|
parameter,
|
|
@@ -446,7 +475,7 @@ class DatabaseHandler:
|
|
|
446
475
|
file_id: dict of GridOut._id
|
|
447
476
|
Dict of database IDs of files.
|
|
448
477
|
"""
|
|
449
|
-
db_name = self.
|
|
478
|
+
db_name = db_name or self.db_name
|
|
450
479
|
|
|
451
480
|
if file_names:
|
|
452
481
|
file_names = [file_names] if not isinstance(file_names, list) else file_names
|
|
@@ -462,8 +491,8 @@ class DatabaseHandler:
|
|
|
462
491
|
if Path(dest).joinpath(file_name).exists():
|
|
463
492
|
instance_ids[file_name] = "file exists"
|
|
464
493
|
else:
|
|
465
|
-
file_path_instance = self._get_file_mongo_db(
|
|
466
|
-
self._write_file_from_mongo_to_disk(
|
|
494
|
+
file_path_instance = self._get_file_mongo_db(db_name, file_name)
|
|
495
|
+
self._write_file_from_mongo_to_disk(db_name, dest, file_path_instance)
|
|
467
496
|
instance_ids[file_name] = file_path_instance._id # pylint: disable=protected-access
|
|
468
497
|
return instance_ids
|
|
469
498
|
|
|
@@ -504,8 +533,7 @@ class DatabaseHandler:
|
|
|
504
533
|
ValueError
|
|
505
534
|
if query returned no results.
|
|
506
535
|
"""
|
|
507
|
-
|
|
508
|
-
collection = self.get_collection(db_name, collection_name)
|
|
536
|
+
collection = self.get_collection(collection_name, db_name=self.db_name)
|
|
509
537
|
posts = list(collection.find(query))
|
|
510
538
|
if not posts:
|
|
511
539
|
raise ValueError(
|
|
@@ -542,7 +570,7 @@ class DatabaseHandler:
|
|
|
542
570
|
pass
|
|
543
571
|
|
|
544
572
|
query = {"model_version": model_version, "collection": collection_name}
|
|
545
|
-
collection = self.get_collection(
|
|
573
|
+
collection = self.get_collection("production_tables", db_name=self.db_name)
|
|
546
574
|
post = collection.find_one(query)
|
|
547
575
|
if not post:
|
|
548
576
|
raise ValueError(f"The following query returned zero results: {query}")
|
|
@@ -569,7 +597,7 @@ class DatabaseHandler:
|
|
|
569
597
|
list
|
|
570
598
|
List of model versions
|
|
571
599
|
"""
|
|
572
|
-
collection = self.get_collection(
|
|
600
|
+
collection = self.get_collection("production_tables", db_name=self.db_name)
|
|
573
601
|
return sorted(
|
|
574
602
|
{post["model_version"] for post in collection.find({"collection": collection_name})}
|
|
575
603
|
)
|
|
@@ -757,8 +785,7 @@ class DatabaseHandler:
|
|
|
757
785
|
production_table: dict
|
|
758
786
|
The production table to add to the DB.
|
|
759
787
|
"""
|
|
760
|
-
|
|
761
|
-
collection = self.get_collection(db_name, "production_tables")
|
|
788
|
+
collection = self.get_collection("production_tables", db_name=db_name or self.db_name)
|
|
762
789
|
self._logger.debug(f"Adding production for {production_table.get('collection')} to to DB")
|
|
763
790
|
collection.insert_one(production_table)
|
|
764
791
|
DatabaseHandler.production_table_cached.clear()
|
|
@@ -789,8 +816,8 @@ class DatabaseHandler:
|
|
|
789
816
|
"""
|
|
790
817
|
par_dict = validate_data.DataValidator.validate_model_parameter(par_dict)
|
|
791
818
|
|
|
792
|
-
db_name = self.
|
|
793
|
-
collection = self.get_collection(
|
|
819
|
+
db_name = db_name or self.db_name
|
|
820
|
+
collection = self.get_collection(collection_name, db_name=db_name)
|
|
794
821
|
|
|
795
822
|
par_dict["value"], _base_unit, _ = value_conversion.get_value_unit_type(
|
|
796
823
|
value=par_dict["value"], unit_str=par_dict.get("unit", None)
|
|
@@ -805,7 +832,7 @@ class DatabaseHandler:
|
|
|
805
832
|
f"corresponding to the {par_dict['parameter']} parameter, must be provided."
|
|
806
833
|
)
|
|
807
834
|
file_path = Path(file_prefix).joinpath(par_dict["value"])
|
|
808
|
-
if not
|
|
835
|
+
if not ascii_handler.is_utf8_file(file_path):
|
|
809
836
|
raise ValueError(f"File is not UTF-8 encoded: {file_path}")
|
|
810
837
|
files_to_add_to_db.add(f"{file_path}")
|
|
811
838
|
|
|
@@ -820,22 +847,6 @@ class DatabaseHandler:
|
|
|
820
847
|
|
|
821
848
|
self._reset_parameter_cache()
|
|
822
849
|
|
|
823
|
-
def _get_db_name(self, db_name=None):
|
|
824
|
-
"""
|
|
825
|
-
Return database name. If not provided, return the default database name.
|
|
826
|
-
|
|
827
|
-
Parameters
|
|
828
|
-
----------
|
|
829
|
-
db_name: str
|
|
830
|
-
Database name
|
|
831
|
-
|
|
832
|
-
Returns
|
|
833
|
-
-------
|
|
834
|
-
str
|
|
835
|
-
Database name
|
|
836
|
-
"""
|
|
837
|
-
return self.mongo_db_config["db_simulation_model"] if db_name is None else db_name
|
|
838
|
-
|
|
839
850
|
def insert_file_to_db(self, file_name, db_name=None, **kwargs):
|
|
840
851
|
"""
|
|
841
852
|
Insert a file to the DB.
|
|
@@ -858,7 +869,7 @@ class DatabaseHandler:
|
|
|
858
869
|
"newly created DB GridOut._id.
|
|
859
870
|
|
|
860
871
|
"""
|
|
861
|
-
db_name = self.
|
|
872
|
+
db_name = db_name or self.db_name
|
|
862
873
|
db = DatabaseHandler.db_client[db_name]
|
|
863
874
|
file_system = gridfs.GridFS(db)
|
|
864
875
|
|
simtools/db/db_model_upload.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
from simtools.io import ascii_handler
|
|
7
7
|
from simtools.utils import names
|
|
8
8
|
|
|
9
9
|
logger = logging.getLogger(__name__)
|
|
@@ -26,7 +26,7 @@ def add_values_from_json_to_db(file, collection, db, db_name, file_prefix):
|
|
|
26
26
|
file_prefix : str
|
|
27
27
|
Path to location of all additional files to be uploaded.
|
|
28
28
|
"""
|
|
29
|
-
par_dict =
|
|
29
|
+
par_dict = ascii_handler.collect_data_from_file(file_name=file)
|
|
30
30
|
logger.debug(
|
|
31
31
|
f"Adding the following parameter to the DB: {par_dict['parameter']} "
|
|
32
32
|
f"version {par_dict['parameter_version']} "
|
|
@@ -119,7 +119,7 @@ def _read_production_table(model_dict, file, model_name):
|
|
|
119
119
|
"design_model": {},
|
|
120
120
|
},
|
|
121
121
|
)
|
|
122
|
-
parameter_dict =
|
|
122
|
+
parameter_dict = ascii_handler.collect_data_from_file(file_name=file)
|
|
123
123
|
logger.debug(f"Reading production table for {array_element} (collection {collection})")
|
|
124
124
|
try:
|
|
125
125
|
if array_element in ("configuration_corsika", "configuration_sim_telarray"):
|
simtools/dependencies.py
CHANGED
|
@@ -14,18 +14,37 @@ import re
|
|
|
14
14
|
import subprocess
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
|
|
17
|
-
import
|
|
17
|
+
import yaml
|
|
18
|
+
|
|
18
19
|
from simtools.db.db_handler import DatabaseHandler
|
|
20
|
+
from simtools.io import ascii_handler
|
|
19
21
|
|
|
20
22
|
_logger = logging.getLogger(__name__)
|
|
21
23
|
|
|
22
24
|
|
|
23
|
-
def get_version_string(db_config=None):
|
|
24
|
-
"""
|
|
25
|
+
def get_version_string(db_config=None, run_time=None):
|
|
26
|
+
"""
|
|
27
|
+
Print the versions of the dependencies.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
db_config : dict, optional
|
|
32
|
+
Database configuration dictionary.
|
|
33
|
+
run_time : list, optional
|
|
34
|
+
Runtime environment command (e.g., Docker).
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
str
|
|
39
|
+
String containing the versions of the dependencies.
|
|
40
|
+
|
|
41
|
+
"""
|
|
25
42
|
return (
|
|
26
43
|
f"Database version: {get_database_version(db_config)}\n"
|
|
27
|
-
f"sim_telarray version: {get_sim_telarray_version()}\n"
|
|
28
|
-
f"CORSIKA version: {get_corsika_version()}\n"
|
|
44
|
+
f"sim_telarray version: {get_sim_telarray_version(run_time)}\n"
|
|
45
|
+
f"CORSIKA version: {get_corsika_version(run_time)}\n"
|
|
46
|
+
f"Build options: {get_build_options(run_time)}\n"
|
|
47
|
+
f"Runtime environment: {run_time if run_time else 'None'}\n"
|
|
29
48
|
)
|
|
30
49
|
|
|
31
50
|
|
|
@@ -50,10 +69,15 @@ def get_database_version(db_config):
|
|
|
50
69
|
return db.mongo_db_config.get("db_simulation_model")
|
|
51
70
|
|
|
52
71
|
|
|
53
|
-
def get_sim_telarray_version():
|
|
72
|
+
def get_sim_telarray_version(run_time):
|
|
54
73
|
"""
|
|
55
74
|
Get the version of the sim_telarray package using 'sim_telarray --version'.
|
|
56
75
|
|
|
76
|
+
Parameters
|
|
77
|
+
----------
|
|
78
|
+
run_time : list, optional
|
|
79
|
+
Runtime environment command (e.g., Docker).
|
|
80
|
+
|
|
57
81
|
Returns
|
|
58
82
|
-------
|
|
59
83
|
str
|
|
@@ -65,24 +89,33 @@ def get_sim_telarray_version():
|
|
|
65
89
|
return None
|
|
66
90
|
sim_telarray_path = Path(sim_telarray_path) / "sim_telarray" / "bin" / "sim_telarray"
|
|
67
91
|
|
|
92
|
+
if run_time is None:
|
|
93
|
+
command = [str(sim_telarray_path), "--version"]
|
|
94
|
+
else:
|
|
95
|
+
command = [*run_time, str(sim_telarray_path), "--version"]
|
|
96
|
+
|
|
97
|
+
_logger.debug(f"Running command: {command}")
|
|
98
|
+
result = subprocess.run(command, capture_output=True, text=True, check=False)
|
|
99
|
+
|
|
68
100
|
# expect stdout with e.g. a line 'Release: 2024.271.0 from 2024-09-27'
|
|
69
|
-
result = subprocess.run(
|
|
70
|
-
[sim_telarray_path, "--version"],
|
|
71
|
-
capture_output=True,
|
|
72
|
-
text=True,
|
|
73
|
-
check=False,
|
|
74
|
-
)
|
|
75
101
|
match = re.search(r"^Release:\s+(.+)", result.stdout, re.MULTILINE)
|
|
76
|
-
|
|
77
102
|
if match:
|
|
78
103
|
return match.group(1).split()[0]
|
|
104
|
+
|
|
105
|
+
_logger.debug(f"Command output stdout: {result.stdout} stderr: {result.stderr}")
|
|
106
|
+
|
|
79
107
|
raise ValueError(f"sim_telarray release not found in {result.stdout}")
|
|
80
108
|
|
|
81
109
|
|
|
82
|
-
def get_corsika_version():
|
|
110
|
+
def get_corsika_version(run_time=None):
|
|
83
111
|
"""
|
|
84
112
|
Get the version of the CORSIKA package.
|
|
85
113
|
|
|
114
|
+
Parameters
|
|
115
|
+
----------
|
|
116
|
+
run_time : list, optional
|
|
117
|
+
Runtime environment command (e.g., Docker).
|
|
118
|
+
|
|
86
119
|
Returns
|
|
87
120
|
-------
|
|
88
121
|
str
|
|
@@ -95,10 +128,15 @@ def get_corsika_version():
|
|
|
95
128
|
return None
|
|
96
129
|
corsika_command = Path(sim_telarray_path) / "corsika-run" / "corsika"
|
|
97
130
|
|
|
131
|
+
if run_time is None:
|
|
132
|
+
command = [str(corsika_command)]
|
|
133
|
+
else:
|
|
134
|
+
command = [*run_time, str(corsika_command)]
|
|
135
|
+
|
|
98
136
|
# Below I do not use the standard context manager because
|
|
99
137
|
# it makes mocking in the tests significantly more difficult
|
|
100
138
|
process = subprocess.Popen( # pylint: disable=consider-using-with
|
|
101
|
-
|
|
139
|
+
command,
|
|
102
140
|
stdout=subprocess.PIPE,
|
|
103
141
|
stderr=subprocess.PIPE,
|
|
104
142
|
stdin=subprocess.PIPE,
|
|
@@ -123,25 +161,50 @@ def get_corsika_version():
|
|
|
123
161
|
if version and re.match(r"\d+\.\d+", version):
|
|
124
162
|
return version
|
|
125
163
|
try:
|
|
126
|
-
build_opts = get_build_options()
|
|
127
|
-
except (FileNotFoundError, TypeError):
|
|
164
|
+
build_opts = get_build_options(run_time)
|
|
165
|
+
except (FileNotFoundError, TypeError, ValueError):
|
|
128
166
|
_logger.warning("Could not get CORSIKA version.")
|
|
129
167
|
return None
|
|
130
168
|
_logger.debug("Getting the CORSIKA version from the build options.")
|
|
131
169
|
return build_opts.get("corsika_version")
|
|
132
170
|
|
|
133
171
|
|
|
134
|
-
def get_build_options():
|
|
172
|
+
def get_build_options(run_time=None):
|
|
135
173
|
"""
|
|
136
174
|
Return CORSIKA / sim_telarray build options.
|
|
137
175
|
|
|
138
176
|
Expects a build_opts.yml file in the sim_telarray directory.
|
|
177
|
+
|
|
178
|
+
Parameters
|
|
179
|
+
----------
|
|
180
|
+
run_time : list, optional
|
|
181
|
+
Runtime environment command (e.g., Docker).
|
|
182
|
+
|
|
183
|
+
Returns
|
|
184
|
+
-------
|
|
185
|
+
dict
|
|
186
|
+
Build options from build_opts.yml file.
|
|
139
187
|
"""
|
|
188
|
+
sim_telarray_path = os.getenv("SIMTOOLS_SIMTEL_PATH")
|
|
189
|
+
if sim_telarray_path is None:
|
|
190
|
+
raise ValueError("SIMTOOLS_SIMTEL_PATH not defined.")
|
|
191
|
+
|
|
192
|
+
build_opts_path = Path(sim_telarray_path) / "build_opts.yml"
|
|
193
|
+
|
|
194
|
+
if run_time is None:
|
|
195
|
+
try:
|
|
196
|
+
return ascii_handler.collect_data_from_file(build_opts_path)
|
|
197
|
+
except FileNotFoundError as exc:
|
|
198
|
+
raise FileNotFoundError("No build_opts.yml file found.") from exc
|
|
199
|
+
|
|
200
|
+
command = [*run_time, "cat", str(build_opts_path)]
|
|
201
|
+
_logger.debug(f"Reading build_opts.yml with command: {command}")
|
|
202
|
+
|
|
203
|
+
result = subprocess.run(command, capture_output=True, text=True, check=False)
|
|
204
|
+
if result.returncode:
|
|
205
|
+
raise FileNotFoundError(f"No build_opts.yml file found in container: {result.stderr}")
|
|
206
|
+
|
|
140
207
|
try:
|
|
141
|
-
return
|
|
142
|
-
|
|
143
|
-
)
|
|
144
|
-
except FileNotFoundError as exc:
|
|
145
|
-
raise FileNotFoundError("No build_opts.yml file found.") from exc
|
|
146
|
-
except TypeError as exc:
|
|
147
|
-
raise TypeError("SIMTOOLS_SIMTEL_PATH not defined.") from exc
|
|
208
|
+
return yaml.safe_load(result.stdout)
|
|
209
|
+
except yaml.YAMLError as exc:
|
|
210
|
+
raise ValueError(f"Error parsing build_opts.yml from container: {exc}") from exc
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"""Helper module for ASCII file operations."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
import tempfile
|
|
6
|
+
import urllib.request
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import astropy.units as u
|
|
10
|
+
import numpy as np
|
|
11
|
+
import yaml
|
|
12
|
+
|
|
13
|
+
from simtools.utils.general import is_url
|
|
14
|
+
|
|
15
|
+
_logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def collect_data_from_file(file_name, yaml_document=None):
|
|
19
|
+
"""
|
|
20
|
+
Collect data from file based on its extension.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
file_name: str
|
|
25
|
+
Name of the yaml/json/ascii file.
|
|
26
|
+
yaml_document: None, int
|
|
27
|
+
Return list of yaml documents or a single document (for yaml files with several documents).
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
data: dict or list
|
|
32
|
+
Data as dict or list.
|
|
33
|
+
"""
|
|
34
|
+
if is_url(file_name):
|
|
35
|
+
return collect_data_from_http(file_name)
|
|
36
|
+
|
|
37
|
+
suffix = Path(file_name).suffix.lower()
|
|
38
|
+
try:
|
|
39
|
+
with open(file_name, encoding="utf-8") as file:
|
|
40
|
+
return _collect_data_from_different_file_types(file, file_name, suffix, yaml_document)
|
|
41
|
+
# broad exception to catch all possible errors in reading the file
|
|
42
|
+
except Exception as exc: # pylint: disable=broad-except
|
|
43
|
+
raise type(exc)(f"Failed to read file {file_name}: {exc}") from exc
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _collect_data_from_different_file_types(file, file_name, suffix, yaml_document):
|
|
47
|
+
"""Collect data from different file types."""
|
|
48
|
+
if suffix == ".json":
|
|
49
|
+
return json.load(file)
|
|
50
|
+
if suffix in (".list", ".txt"):
|
|
51
|
+
return [line.strip() for line in file.readlines()]
|
|
52
|
+
if suffix in [".yml", ".yaml"]:
|
|
53
|
+
return _collect_data_from_yaml_file(file, file_name, yaml_document)
|
|
54
|
+
raise TypeError(f"File type {suffix} not supported.")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _collect_data_from_yaml_file(file, file_name, yaml_document):
|
|
58
|
+
"""Collect data from a yaml file (allow for multi-document yaml files)."""
|
|
59
|
+
try:
|
|
60
|
+
return yaml.safe_load(file)
|
|
61
|
+
except yaml.constructor.ConstructorError:
|
|
62
|
+
return _load_yaml_using_astropy(file)
|
|
63
|
+
except yaml.composer.ComposerError:
|
|
64
|
+
pass
|
|
65
|
+
file.seek(0)
|
|
66
|
+
if yaml_document is None:
|
|
67
|
+
return list(yaml.safe_load_all(file))
|
|
68
|
+
try:
|
|
69
|
+
return list(yaml.safe_load_all(file))[yaml_document]
|
|
70
|
+
except IndexError as exc:
|
|
71
|
+
raise IndexError(
|
|
72
|
+
f"Failed to read file {file_name}: YAML document index {yaml_document} is out of range."
|
|
73
|
+
) from exc
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _load_yaml_using_astropy(file):
|
|
77
|
+
"""
|
|
78
|
+
Load a yaml file using astropy's yaml loader.
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
file: file
|
|
83
|
+
File to be loaded.
|
|
84
|
+
|
|
85
|
+
Returns
|
|
86
|
+
-------
|
|
87
|
+
dict
|
|
88
|
+
Dictionary containing the file content.
|
|
89
|
+
"""
|
|
90
|
+
# pylint: disable=import-outside-toplevel
|
|
91
|
+
import astropy.io.misc.yaml as astropy_yaml
|
|
92
|
+
|
|
93
|
+
file.seek(0)
|
|
94
|
+
return astropy_yaml.load(file)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def collect_data_from_http(url):
|
|
98
|
+
"""
|
|
99
|
+
Download yaml or json file from url and return it contents as dict.
|
|
100
|
+
|
|
101
|
+
File is downloaded as a temporary file and deleted afterwards.
|
|
102
|
+
|
|
103
|
+
Parameters
|
|
104
|
+
----------
|
|
105
|
+
url: str
|
|
106
|
+
URL of the yaml/json file.
|
|
107
|
+
|
|
108
|
+
Returns
|
|
109
|
+
-------
|
|
110
|
+
dict
|
|
111
|
+
Dictionary containing the file content.
|
|
112
|
+
|
|
113
|
+
Raises
|
|
114
|
+
------
|
|
115
|
+
TypeError
|
|
116
|
+
If url is not a valid URL.
|
|
117
|
+
FileNotFoundError
|
|
118
|
+
If downloading the yaml file fails.
|
|
119
|
+
|
|
120
|
+
"""
|
|
121
|
+
try:
|
|
122
|
+
with tempfile.NamedTemporaryFile(mode="w+t") as tmp_file:
|
|
123
|
+
urllib.request.urlretrieve(url, tmp_file.name)
|
|
124
|
+
data = _collect_data_from_different_file_types(
|
|
125
|
+
tmp_file, url, Path(url).suffix.lower(), None
|
|
126
|
+
)
|
|
127
|
+
except TypeError as exc:
|
|
128
|
+
raise TypeError(f"Invalid url {url}") from exc
|
|
129
|
+
except urllib.error.HTTPError as exc:
|
|
130
|
+
raise FileNotFoundError(f"Failed to download file from {url}") from exc
|
|
131
|
+
|
|
132
|
+
_logger.debug(f"Downloaded file from {url}")
|
|
133
|
+
return data
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def read_file_encoded_in_utf_or_latin(file_name):
|
|
137
|
+
"""
|
|
138
|
+
Read a file encoded in UTF-8 or Latin-1.
|
|
139
|
+
|
|
140
|
+
Parameters
|
|
141
|
+
----------
|
|
142
|
+
file_name: str
|
|
143
|
+
Name of the file to be read.
|
|
144
|
+
|
|
145
|
+
Returns
|
|
146
|
+
-------
|
|
147
|
+
list
|
|
148
|
+
List of lines read from the file.
|
|
149
|
+
|
|
150
|
+
Raises
|
|
151
|
+
------
|
|
152
|
+
UnicodeDecodeError
|
|
153
|
+
If the file cannot be decoded using UTF-8 or Latin-1.
|
|
154
|
+
"""
|
|
155
|
+
try:
|
|
156
|
+
with open(file_name, encoding="utf-8") as file:
|
|
157
|
+
lines = file.readlines()
|
|
158
|
+
except UnicodeDecodeError:
|
|
159
|
+
_logger.debug("Unable to decode file using UTF-8. Trying Latin-1.")
|
|
160
|
+
try:
|
|
161
|
+
with open(file_name, encoding="latin-1") as file:
|
|
162
|
+
lines = file.readlines()
|
|
163
|
+
except UnicodeDecodeError as exc:
|
|
164
|
+
msg = f"Unable to decode file {file_name} using UTF-8 or Latin-1."
|
|
165
|
+
raise UnicodeDecodeError(exc.encoding, exc.object, exc.start, exc.end, msg) from exc
|
|
166
|
+
|
|
167
|
+
return lines
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def is_utf8_file(file_name):
|
|
171
|
+
"""
|
|
172
|
+
Check if a file is encoded in UTF-8.
|
|
173
|
+
|
|
174
|
+
Parameters
|
|
175
|
+
----------
|
|
176
|
+
file_name: str, Path
|
|
177
|
+
Name of the file to be checked.
|
|
178
|
+
|
|
179
|
+
Returns
|
|
180
|
+
-------
|
|
181
|
+
bool
|
|
182
|
+
True if the file is encoded in UTF-8, False otherwise.
|
|
183
|
+
"""
|
|
184
|
+
try:
|
|
185
|
+
with open(file_name, encoding="utf-8") as file:
|
|
186
|
+
file.read()
|
|
187
|
+
return True
|
|
188
|
+
except UnicodeDecodeError:
|
|
189
|
+
return False
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def write_data_to_file(data, output_file, sort_keys=False, numpy_types=False):
|
|
193
|
+
"""
|
|
194
|
+
Write structured data to JSON or YAML file.
|
|
195
|
+
|
|
196
|
+
The file type is determined by the file extension.
|
|
197
|
+
|
|
198
|
+
Parameters
|
|
199
|
+
----------
|
|
200
|
+
data: dict or list
|
|
201
|
+
Data to be written to the file.
|
|
202
|
+
output_file: str or Path
|
|
203
|
+
Name of the file to be written.
|
|
204
|
+
sort_keys: bool, optional
|
|
205
|
+
If True, sort the keys.
|
|
206
|
+
numpy_types: bool, optional
|
|
207
|
+
If True, convert numpy types to native Python types.
|
|
208
|
+
"""
|
|
209
|
+
output_file = Path(output_file)
|
|
210
|
+
if output_file.suffix.lower() == ".json":
|
|
211
|
+
return _write_to_json(data, output_file, sort_keys, numpy_types)
|
|
212
|
+
if output_file.suffix.lower() in [".yml", ".yaml"]:
|
|
213
|
+
return _write_to_yaml(data, output_file, sort_keys)
|
|
214
|
+
|
|
215
|
+
raise ValueError(
|
|
216
|
+
f"Unsupported file type {output_file.suffix}. Only .json, .yml, and .yaml are supported."
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def _write_to_json(data, output_file, sort_keys, numpy_types):
|
|
221
|
+
"""
|
|
222
|
+
Write data to a JSON file.
|
|
223
|
+
|
|
224
|
+
Parameters
|
|
225
|
+
----------
|
|
226
|
+
data: dict or list
|
|
227
|
+
Data to be written to the file.
|
|
228
|
+
output_file: Path
|
|
229
|
+
Name of the file to be written.
|
|
230
|
+
sort_keys: bool
|
|
231
|
+
If True, sort the keys.
|
|
232
|
+
numpy_types: bool
|
|
233
|
+
If True, convert numpy types to native Python types.
|
|
234
|
+
"""
|
|
235
|
+
with open(output_file, "w", encoding="utf-8") as file:
|
|
236
|
+
json.dump(
|
|
237
|
+
data,
|
|
238
|
+
file,
|
|
239
|
+
indent=4,
|
|
240
|
+
sort_keys=sort_keys,
|
|
241
|
+
cls=JsonNumpyEncoder if numpy_types else None,
|
|
242
|
+
)
|
|
243
|
+
file.write("\n")
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def _write_to_yaml(data, output_file, sort_keys):
|
|
247
|
+
"""
|
|
248
|
+
Write data to a YAML file.
|
|
249
|
+
|
|
250
|
+
Parameters
|
|
251
|
+
----------
|
|
252
|
+
data: dict or list
|
|
253
|
+
Data to be written to the file.
|
|
254
|
+
output_file: Path
|
|
255
|
+
Name of the file to be written.
|
|
256
|
+
sort_keys: bool
|
|
257
|
+
If True, sort the keys.
|
|
258
|
+
|
|
259
|
+
"""
|
|
260
|
+
with open(output_file, "w", encoding="utf-8") as file:
|
|
261
|
+
yaml.dump(data, file, indent=4, sort_keys=sort_keys, explicit_start=True)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
class JsonNumpyEncoder(json.JSONEncoder):
|
|
265
|
+
"""Convert numpy to python types as accepted by json.dump."""
|
|
266
|
+
|
|
267
|
+
def default(self, o):
|
|
268
|
+
"""Return default encoder."""
|
|
269
|
+
if isinstance(o, np.floating):
|
|
270
|
+
return float(o)
|
|
271
|
+
if isinstance(o, np.integer):
|
|
272
|
+
return int(o)
|
|
273
|
+
if isinstance(o, np.ndarray):
|
|
274
|
+
return o.tolist()
|
|
275
|
+
if isinstance(o, u.core.CompositeUnit | u.core.IrreducibleUnit | u.core.Unit):
|
|
276
|
+
return str(o) if o != u.dimensionless_unscaled else None
|
|
277
|
+
if np.issubdtype(type(o), np.bool_):
|
|
278
|
+
return bool(o)
|
|
279
|
+
return super().default(o)
|