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
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
|
|
@@ -451,7 +475,7 @@ class DatabaseHandler:
|
|
|
451
475
|
file_id: dict of GridOut._id
|
|
452
476
|
Dict of database IDs of files.
|
|
453
477
|
"""
|
|
454
|
-
db_name = self.
|
|
478
|
+
db_name = db_name or self.db_name
|
|
455
479
|
|
|
456
480
|
if file_names:
|
|
457
481
|
file_names = [file_names] if not isinstance(file_names, list) else file_names
|
|
@@ -467,8 +491,8 @@ class DatabaseHandler:
|
|
|
467
491
|
if Path(dest).joinpath(file_name).exists():
|
|
468
492
|
instance_ids[file_name] = "file exists"
|
|
469
493
|
else:
|
|
470
|
-
file_path_instance = self._get_file_mongo_db(
|
|
471
|
-
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)
|
|
472
496
|
instance_ids[file_name] = file_path_instance._id # pylint: disable=protected-access
|
|
473
497
|
return instance_ids
|
|
474
498
|
|
|
@@ -509,8 +533,7 @@ class DatabaseHandler:
|
|
|
509
533
|
ValueError
|
|
510
534
|
if query returned no results.
|
|
511
535
|
"""
|
|
512
|
-
|
|
513
|
-
collection = self.get_collection(db_name, collection_name)
|
|
536
|
+
collection = self.get_collection(collection_name, db_name=self.db_name)
|
|
514
537
|
posts = list(collection.find(query))
|
|
515
538
|
if not posts:
|
|
516
539
|
raise ValueError(
|
|
@@ -547,7 +570,7 @@ class DatabaseHandler:
|
|
|
547
570
|
pass
|
|
548
571
|
|
|
549
572
|
query = {"model_version": model_version, "collection": collection_name}
|
|
550
|
-
collection = self.get_collection(
|
|
573
|
+
collection = self.get_collection("production_tables", db_name=self.db_name)
|
|
551
574
|
post = collection.find_one(query)
|
|
552
575
|
if not post:
|
|
553
576
|
raise ValueError(f"The following query returned zero results: {query}")
|
|
@@ -574,7 +597,7 @@ class DatabaseHandler:
|
|
|
574
597
|
list
|
|
575
598
|
List of model versions
|
|
576
599
|
"""
|
|
577
|
-
collection = self.get_collection(
|
|
600
|
+
collection = self.get_collection("production_tables", db_name=self.db_name)
|
|
578
601
|
return sorted(
|
|
579
602
|
{post["model_version"] for post in collection.find({"collection": collection_name})}
|
|
580
603
|
)
|
|
@@ -762,8 +785,7 @@ class DatabaseHandler:
|
|
|
762
785
|
production_table: dict
|
|
763
786
|
The production table to add to the DB.
|
|
764
787
|
"""
|
|
765
|
-
|
|
766
|
-
collection = self.get_collection(db_name, "production_tables")
|
|
788
|
+
collection = self.get_collection("production_tables", db_name=db_name or self.db_name)
|
|
767
789
|
self._logger.debug(f"Adding production for {production_table.get('collection')} to to DB")
|
|
768
790
|
collection.insert_one(production_table)
|
|
769
791
|
DatabaseHandler.production_table_cached.clear()
|
|
@@ -794,8 +816,8 @@ class DatabaseHandler:
|
|
|
794
816
|
"""
|
|
795
817
|
par_dict = validate_data.DataValidator.validate_model_parameter(par_dict)
|
|
796
818
|
|
|
797
|
-
db_name = self.
|
|
798
|
-
collection = self.get_collection(
|
|
819
|
+
db_name = db_name or self.db_name
|
|
820
|
+
collection = self.get_collection(collection_name, db_name=db_name)
|
|
799
821
|
|
|
800
822
|
par_dict["value"], _base_unit, _ = value_conversion.get_value_unit_type(
|
|
801
823
|
value=par_dict["value"], unit_str=par_dict.get("unit", None)
|
|
@@ -810,7 +832,7 @@ class DatabaseHandler:
|
|
|
810
832
|
f"corresponding to the {par_dict['parameter']} parameter, must be provided."
|
|
811
833
|
)
|
|
812
834
|
file_path = Path(file_prefix).joinpath(par_dict["value"])
|
|
813
|
-
if not
|
|
835
|
+
if not ascii_handler.is_utf8_file(file_path):
|
|
814
836
|
raise ValueError(f"File is not UTF-8 encoded: {file_path}")
|
|
815
837
|
files_to_add_to_db.add(f"{file_path}")
|
|
816
838
|
|
|
@@ -825,22 +847,6 @@ class DatabaseHandler:
|
|
|
825
847
|
|
|
826
848
|
self._reset_parameter_cache()
|
|
827
849
|
|
|
828
|
-
def _get_db_name(self, db_name=None):
|
|
829
|
-
"""
|
|
830
|
-
Return database name. If not provided, return the default database name.
|
|
831
|
-
|
|
832
|
-
Parameters
|
|
833
|
-
----------
|
|
834
|
-
db_name: str
|
|
835
|
-
Database name
|
|
836
|
-
|
|
837
|
-
Returns
|
|
838
|
-
-------
|
|
839
|
-
str
|
|
840
|
-
Database name
|
|
841
|
-
"""
|
|
842
|
-
return self.mongo_db_config["db_simulation_model"] if db_name is None else db_name
|
|
843
|
-
|
|
844
850
|
def insert_file_to_db(self, file_name, db_name=None, **kwargs):
|
|
845
851
|
"""
|
|
846
852
|
Insert a file to the DB.
|
|
@@ -863,7 +869,7 @@ class DatabaseHandler:
|
|
|
863
869
|
"newly created DB GridOut._id.
|
|
864
870
|
|
|
865
871
|
"""
|
|
866
|
-
db_name = self.
|
|
872
|
+
db_name = db_name or self.db_name
|
|
867
873
|
db = DatabaseHandler.db_client[db_name]
|
|
868
874
|
file_system = gridfs.GridFS(db)
|
|
869
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)
|