gammasimtools 0.18.0__py3-none-any.whl → 0.20.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/METADATA +24 -69
- gammasimtools-0.20.0.dist-info/RECORD +395 -0
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/entry_points.txt +11 -4
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/licenses/LICENSE +1 -1
- simtools/_version.py +16 -3
- simtools/applications/calculate_incident_angles.py +182 -0
- simtools/applications/convert_all_model_parameters_from_simtel.py +4 -3
- simtools/applications/convert_geo_coordinates_of_array_elements.py +3 -3
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +17 -14
- simtools/applications/db_add_value_from_json_to_db.py +8 -10
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +8 -13
- simtools/applications/db_generate_compound_indexes.py +65 -0
- simtools/applications/db_get_file_from_db.py +12 -24
- simtools/applications/db_get_parameter_from_db.py +4 -4
- simtools/applications/db_inspect_databases.py +20 -10
- simtools/applications/derive_mirror_rnda.py +17 -11
- simtools/applications/derive_psf_parameters.py +59 -309
- simtools/applications/derive_trigger_rates.py +91 -0
- simtools/applications/docs_produce_array_element_report.py +1 -1
- simtools/applications/docs_produce_calibration_reports.py +1 -1
- simtools/applications/docs_produce_model_parameter_reports.py +1 -1
- simtools/applications/docs_produce_simulation_configuration_report.py +1 -1
- simtools/applications/generate_corsika_histograms.py +1 -1
- simtools/applications/generate_default_metadata.py +8 -24
- simtools/applications/generate_simtel_event_data.py +11 -11
- simtools/applications/maintain_simulation_model_add_production_table.py +71 -0
- simtools/applications/maintain_simulation_model_compare_productions.py +98 -0
- simtools/applications/{verify_simulation_model_production_tables.py → maintain_simulation_model_verify_production_tables.py} +9 -1
- simtools/applications/merge_tables.py +2 -2
- simtools/applications/plot_array_layout.py +3 -3
- simtools/applications/plot_simtel_events.py +421 -0
- simtools/applications/plot_tabular_data.py +9 -2
- simtools/applications/plot_tabular_data_for_model_parameter.py +2 -1
- simtools/applications/print_version.py +8 -9
- simtools/applications/production_derive_corsika_limits.py +6 -7
- simtools/applications/production_derive_statistics.py +1 -1
- simtools/applications/production_generate_grid.py +2 -2
- simtools/applications/production_merge_corsika_limits.py +214 -0
- simtools/applications/run_application.py +47 -113
- simtools/applications/simulate_calibration_events.py +166 -0
- simtools/applications/simulate_flasher.py +141 -0
- simtools/applications/{simulate_light_emission.py → simulate_illuminator.py} +35 -99
- simtools/applications/simulate_prod.py +6 -24
- simtools/applications/simulate_prod_htcondor_generator.py +7 -0
- simtools/applications/submit_array_layouts.py +2 -1
- simtools/applications/submit_model_parameter_from_external.py +1 -1
- simtools/applications/validate_camera_efficiency.py +30 -12
- simtools/applications/validate_camera_fov.py +1 -1
- simtools/applications/validate_cumulative_psf.py +1 -1
- simtools/applications/validate_file_using_schema.py +9 -5
- simtools/applications/validate_optics.py +1 -1
- simtools/camera/camera_efficiency.py +61 -45
- simtools/camera/single_photon_electron_spectrum.py +1 -1
- simtools/configuration/commandline_parser.py +46 -11
- simtools/configuration/configurator.py +4 -4
- simtools/corsika/corsika_config.py +45 -25
- simtools/corsika/corsika_histograms.py +6 -5
- simtools/data_model/data_reader.py +2 -3
- simtools/data_model/metadata_collector.py +32 -36
- simtools/data_model/metadata_model.py +15 -12
- simtools/data_model/model_data_writer.py +13 -32
- simtools/data_model/schema.py +74 -24
- simtools/data_model/validate_data.py +42 -12
- simtools/db/db_handler.py +125 -62
- simtools/db/db_model_upload.py +14 -19
- simtools/dependencies.py +98 -30
- simtools/io/ascii_handler.py +279 -0
- simtools/{io_operations → io}/io_handler.py +25 -3
- simtools/job_execution/htcondor_script_generator.py +15 -4
- simtools/layout/array_layout.py +1 -1
- simtools/layout/array_layout_utils.py +51 -12
- simtools/model/array_model.py +41 -5
- simtools/model/flasher_model.py +106 -0
- simtools/model/model_parameter.py +4 -4
- simtools/model/model_repository.py +197 -2
- simtools/model/site_model.py +25 -0
- simtools/model/telescope_model.py +3 -1
- simtools/production_configuration/derive_corsika_limits.py +336 -427
- simtools/production_configuration/derive_production_statistics_handler.py +7 -6
- simtools/production_configuration/generate_production_grid.py +9 -11
- simtools/production_configuration/merge_corsika_limits.py +528 -0
- simtools/ray_tracing/incident_angles.py +706 -0
- simtools/ray_tracing/mirror_panel_psf.py +1 -0
- simtools/ray_tracing/psf_parameter_optimisation.py +792 -0
- simtools/ray_tracing/ray_tracing.py +6 -2
- simtools/reporting/docs_read_parameters.py +150 -62
- simtools/runners/corsika_runner.py +1 -1
- simtools/runners/corsika_simtel_runner.py +14 -5
- simtools/runners/runner_services.py +10 -5
- simtools/runners/simtools_runner.py +267 -0
- simtools/schemas/application_workflow.metaschema.yml +101 -68
- simtools/schemas/input/MST_mirror_2f_measurements.schema.yml +1 -1
- simtools/schemas/input/single_pe_spectrum.schema.yml +1 -1
- simtools/schemas/metadata.metaschema.yml +577 -3
- simtools/schemas/model_parameter.metaschema.yml +6 -6
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +4 -4
- simtools/schemas/model_parameters/adjust_gain.schema.yml +1 -1
- simtools/schemas/model_parameters/altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/array_coordinates.schema.yml +1 -1
- simtools/schemas/model_parameters/array_coordinates_UTM.schema.yml +1 -1
- simtools/schemas/model_parameters/array_element_position_ground.schema.yml +1 -1
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +1 -1
- simtools/schemas/model_parameters/array_layouts.schema.yml +1 -1
- simtools/schemas/model_parameters/array_triggers.schema.yml +1 -1
- simtools/schemas/model_parameters/array_window.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_shaping.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/atmospheric_profile.schema.yml +1 -1
- simtools/schemas/model_parameters/atmospheric_transmission.schema.yml +1 -1
- simtools/schemas/model_parameters/axes_offsets.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_body_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_body_shape.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_config_file.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_config_rotate.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_depth.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_filter.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_filter_incidence_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_pixels.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_transmission.schema.yml +1 -1
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
- simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_cherenkov_photon_bunch_size.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_cherenkov_photon_wavelength_range.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_first_interaction_height.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_longitudinal_shower_development.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_observation_level.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_particle_kinetic_energy_cutoff.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +3 -3
- simtools/schemas/model_parameters/dark_events.schema.yml +1 -1
- simtools/schemas/model_parameters/default_trigger.schema.yml +1 -1
- simtools/schemas/model_parameters/design_model.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_ac_coupled.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_start.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/dish_shape_length.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_pedsub.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +1 -1
- simtools/schemas/model_parameters/effective_focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/epsg_code.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_ac_coupled.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_long_event_threshold.schema.yml +35 -0
- simtools/schemas/model_parameters/fadc_long_sum_bins.schema.yml +41 -0
- simtools/schemas/model_parameters/fadc_long_sum_offset.schema.yml +38 -0
- simtools/schemas/model_parameters/fadc_max_signal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_max_sum.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_mhz.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_noise.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fake_mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/flatfielding.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_surface_parameters.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_surface_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/focus_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/gain_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_horizontal.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_rotation.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_vertical.schema.yml +1 -1
- simtools/schemas/model_parameters/hg_lg_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_events.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_external_trigger.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_exptime.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_sigtime.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_twidth.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_var_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_wavelength.schema.yml +1 -1
- simtools/schemas/model_parameters/led_events.schema.yml +1 -1
- simtools/schemas/model_parameters/led_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/led_pulse_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/led_pulse_sigtime.schema.yml +1 -1
- simtools/schemas/model_parameters/led_var_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +50 -1
- simtools/schemas/model_parameters/min_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/min_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_class.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_panel_2f_measurements.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +1 -1
- simtools/schemas/model_parameters/multiplicity_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/muon_mono_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_gain_drop_scale.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_offaxis.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +2 -2
- simtools/schemas/model_parameters/nsb_reference_value.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_scaling_factor.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_sky_map.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_spectrum.schema.yml +23 -30
- simtools/schemas/model_parameters/num_gains.schema.yml +1 -1
- simtools/schemas/model_parameters/only_triggered_telescopes.schema.yml +1 -1
- simtools/schemas/model_parameters/optics_properties.schema.yml +1 -1
- simtools/schemas/model_parameters/parabolic_dish.schema.yml +1 -1
- simtools/schemas/model_parameters/pedestal_events.schema.yml +1 -1
- simtools/schemas/model_parameters/photon_delay.schema.yml +1 -1
- simtools/schemas/model_parameters/photons_per_run.schema.yml +1 -1
- simtools/schemas/model_parameters/pixel_cells.schema.yml +1 -1
- simtools/schemas/model_parameters/pixels_parallel.schema.yml +1 -1
- simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_average_gain.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_gain_index.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_transit_time.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_hole_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_incidence_angle.schema.yml +11 -1
- simtools/schemas/model_parameters/primary_mirror_parameters.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_segmentation.schema.yml +1 -1
- simtools/schemas/model_parameters/qe_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/quantum_efficiency.schema.yml +1 -1
- simtools/schemas/model_parameters/random_focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/random_generator.schema.yml +1 -1
- simtools/schemas/model_parameters/random_mono_probability.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_latitude.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_longitude.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_utm_east.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_utm_north.schema.yml +1 -1
- simtools/schemas/model_parameters/sampled_output.schema.yml +1 -1
- simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_baffle.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_hole_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_incidence_angle.schema.yml +11 -1
- simtools/schemas/model_parameters/secondary_mirror_parameters.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_reflectivity.schema.yml +11 -1
- simtools/schemas/model_parameters/secondary_mirror_segmentation.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_shadow_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_shadow_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/stars.schema.yml +2 -2
- simtools/schemas/model_parameters/store_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/tailcut_scale.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_axis_height.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_random_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_random_error.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_transmission.schema.yml +1 -1
- simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +1 -1
- simtools/schemas/model_parameters/teltrig_min_time.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_jitter.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_current_limit.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_pixels.schema.yml +1 -1
- simtools/schemas/plot_configuration.metaschema.yml +5 -2
- simtools/schemas/production_configuration_metrics.schema.yml +12 -2
- simtools/schemas/production_tables.schema.yml +7 -2
- simtools/simtel/simtel_config_reader.py +2 -2
- simtools/simtel/simtel_config_writer.py +33 -23
- simtools/simtel/simtel_io_event_histograms.py +483 -0
- simtools/simtel/simtel_io_event_reader.py +65 -43
- simtools/simtel/simtel_io_event_writer.py +40 -20
- simtools/simtel/simtel_io_metadata.py +1 -1
- simtools/simtel/simtel_table_reader.py +95 -13
- simtools/simtel/simulator_array.py +138 -10
- simtools/simtel/simulator_camera_efficiency.py +32 -23
- simtools/simtel/simulator_light_emission.py +437 -271
- simtools/simtel/simulator_ray_tracing.py +1 -1
- simtools/simulator.py +105 -147
- simtools/telescope_trigger_rates.py +119 -0
- simtools/testing/configuration.py +24 -26
- simtools/testing/helpers.py +2 -2
- simtools/testing/log_inspector.py +52 -0
- simtools/testing/validate_output.py +87 -37
- simtools/utils/general.py +125 -255
- simtools/utils/geometry.py +56 -0
- simtools/utils/names.py +1 -1
- simtools/visualization/legend_handlers.py +180 -264
- simtools/visualization/plot_array_layout.py +20 -8
- simtools/visualization/plot_incident_angles.py +431 -0
- simtools/visualization/plot_pixels.py +1 -1
- simtools/visualization/plot_simtel_event_histograms.py +376 -0
- simtools/visualization/plot_simtel_events.py +816 -0
- simtools/visualization/plot_tables.py +133 -37
- simtools/visualization/visualize.py +1 -100
- gammasimtools-0.18.0.dist-info/RECORD +0 -376
- simtools/applications/calculate_trigger_rate.py +0 -187
- simtools/applications/generate_sim_telarray_histograms.py +0 -196
- simtools/production_configuration/derive_corsika_limits_grid.py +0 -232
- simtools/simtel/simtel_io_histogram.py +0 -621
- simtools/simtel/simtel_io_histograms.py +0 -552
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.18.0.dist-info → gammasimtools-0.20.0.dist-info}/top_level.txt +0 -0
- /simtools/{io_operations → io}/hdf5_handler.py +0 -0
- /simtools/{io_operations → io}/legacy_data_handler.py +0 -0
- /simtools/{io_operations/io_table_handler.py → io/table_handler.py} +0 -0
|
@@ -11,13 +11,11 @@ import logging
|
|
|
11
11
|
import uuid
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
|
|
14
|
-
import yaml
|
|
15
|
-
|
|
16
14
|
import simtools.utils.general as gen
|
|
17
15
|
import simtools.version
|
|
18
16
|
from simtools.constants import METADATA_JSON_SCHEMA
|
|
19
17
|
from simtools.data_model import metadata_model, schema
|
|
20
|
-
from simtools.
|
|
18
|
+
from simtools.io import ascii_handler, io_handler
|
|
21
19
|
from simtools.utils import names
|
|
22
20
|
|
|
23
21
|
__all__ = ["MetadataCollector"]
|
|
@@ -41,33 +39,36 @@ class MetadataCollector:
|
|
|
41
39
|
Command line parameters
|
|
42
40
|
metadata_file_name: str
|
|
43
41
|
Name of metadata file (only required when args_dict is None)
|
|
44
|
-
|
|
45
|
-
Name of
|
|
42
|
+
model_parameter_name: str
|
|
43
|
+
Name of model parameter
|
|
46
44
|
observatory: str
|
|
47
45
|
Name of observatory (default: "cta")
|
|
48
46
|
clean_meta: bool
|
|
49
47
|
Clean metadata from None values and empty lists (default: True)
|
|
48
|
+
schema_version: str
|
|
49
|
+
Version of the metadata schema to use (default: 'latest')
|
|
50
50
|
"""
|
|
51
51
|
|
|
52
52
|
def __init__(
|
|
53
53
|
self,
|
|
54
|
-
args_dict,
|
|
54
|
+
args_dict=None,
|
|
55
55
|
metadata_file_name=None,
|
|
56
|
-
|
|
56
|
+
model_parameter_name=None,
|
|
57
57
|
observatory="cta",
|
|
58
58
|
clean_meta=True,
|
|
59
|
+
schema_version="latest",
|
|
59
60
|
):
|
|
60
61
|
"""Initialize metadata collector."""
|
|
61
62
|
self._logger = logging.getLogger(__name__)
|
|
62
63
|
self.observatory = observatory
|
|
63
64
|
self.io_handler = io_handler.IOHandler()
|
|
64
65
|
|
|
65
|
-
self.args_dict = args_dict
|
|
66
|
-
self.
|
|
66
|
+
self.args_dict = args_dict or {}
|
|
67
|
+
self.model_parameter_name = model_parameter_name
|
|
67
68
|
self.schema_file = None
|
|
68
69
|
self.schema_dict = None
|
|
69
|
-
self.top_level_meta =
|
|
70
|
-
|
|
70
|
+
self.top_level_meta = metadata_model.get_default_metadata_dict(
|
|
71
|
+
schema_version=schema_version
|
|
71
72
|
)
|
|
72
73
|
self.input_metadata = self._read_input_metadata_from_file(metadata_file_name)
|
|
73
74
|
self.collect_meta_data()
|
|
@@ -119,7 +120,7 @@ class MetadataCollector:
|
|
|
119
120
|
collector = MetadataCollector(args_dict)
|
|
120
121
|
collector.write(output_file, add_activity_name=add_activity_name)
|
|
121
122
|
|
|
122
|
-
def write(self, yml_file=None, keys_lower_case=
|
|
123
|
+
def write(self, yml_file=None, keys_lower_case=True, add_activity_name=False):
|
|
123
124
|
"""
|
|
124
125
|
Write toplevel metadata to file (yaml file format).
|
|
125
126
|
|
|
@@ -155,16 +156,13 @@ class MetadataCollector:
|
|
|
155
156
|
|
|
156
157
|
try:
|
|
157
158
|
yml_file = names.file_name_with_version(yml_file, suffix)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
gen.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
sort_keys=False,
|
|
166
|
-
explicit_start=True,
|
|
167
|
-
)
|
|
159
|
+
ascii_handler.write_data_to_file(
|
|
160
|
+
data=gen.change_dict_keys_case(
|
|
161
|
+
gen.remove_substring_recursively_from_dict(metadata, substring="\n"),
|
|
162
|
+
keys_lower_case,
|
|
163
|
+
),
|
|
164
|
+
output_file=yml_file,
|
|
165
|
+
)
|
|
168
166
|
self._logger.info(f"Writing metadata to {yml_file}")
|
|
169
167
|
return yml_file
|
|
170
168
|
except FileNotFoundError as exc:
|
|
@@ -198,10 +196,10 @@ class MetadataCollector:
|
|
|
198
196
|
except KeyError:
|
|
199
197
|
pass
|
|
200
198
|
|
|
201
|
-
# from
|
|
202
|
-
if self.
|
|
203
|
-
self._logger.debug(f"Schema file from data model name: {self.
|
|
204
|
-
return str(schema.get_model_parameter_schema_file(self.
|
|
199
|
+
# from model parameter name
|
|
200
|
+
if self.model_parameter_name:
|
|
201
|
+
self._logger.debug(f"Schema file from data model name: {self.model_parameter_name}")
|
|
202
|
+
return str(schema.get_model_parameter_schema_file(self.model_parameter_name))
|
|
205
203
|
|
|
206
204
|
# from first entry in input metadata (least preferred)
|
|
207
205
|
try:
|
|
@@ -225,7 +223,7 @@ class MetadataCollector:
|
|
|
225
223
|
|
|
226
224
|
"""
|
|
227
225
|
try:
|
|
228
|
-
return
|
|
226
|
+
return ascii_handler.collect_data_from_file(file_name=self.schema_file)
|
|
229
227
|
except TypeError:
|
|
230
228
|
self._logger.debug(f"No valid schema file provided ({self.schema_file}).")
|
|
231
229
|
return {}
|
|
@@ -334,7 +332,7 @@ class MetadataCollector:
|
|
|
334
332
|
|
|
335
333
|
Raises
|
|
336
334
|
------
|
|
337
|
-
|
|
335
|
+
ValueError:
|
|
338
336
|
if metadata cannot be read from file.
|
|
339
337
|
KeyError:
|
|
340
338
|
if metadata does not exist
|
|
@@ -365,7 +363,7 @@ class MetadataCollector:
|
|
|
365
363
|
)
|
|
366
364
|
continue
|
|
367
365
|
else:
|
|
368
|
-
raise
|
|
366
|
+
raise ValueError(f"Unknown metadata file format: {metadata_file}")
|
|
369
367
|
|
|
370
368
|
schema.validate_dict_using_schema(_input_metadata, schema_file=METADATA_JSON_SCHEMA)
|
|
371
369
|
metadata.append(gen.change_dict_keys_case(_input_metadata, lower_case=True))
|
|
@@ -391,16 +389,14 @@ class MetadataCollector:
|
|
|
391
389
|
def _read_input_metadata_from_yml_or_json(self, metadata_file_name):
|
|
392
390
|
"""Read input metadata from yml or json file."""
|
|
393
391
|
try:
|
|
394
|
-
_input_metadata =
|
|
392
|
+
_input_metadata = ascii_handler.collect_data_from_file(file_name=metadata_file_name)
|
|
395
393
|
_json_type_metadata = {"Metadata", "metadata", "METADATA"}.intersection(_input_metadata)
|
|
396
394
|
if len(_json_type_metadata) == 1:
|
|
397
395
|
_input_metadata = _input_metadata[_json_type_metadata.pop()]
|
|
398
396
|
if len(_json_type_metadata) > 1:
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
self._logger.error("Failed reading metadata from %s", metadata_file_name)
|
|
403
|
-
raise exc
|
|
397
|
+
raise ValueError(f"More than one metadata entry found in {metadata_file_name}")
|
|
398
|
+
except FileNotFoundError as exc:
|
|
399
|
+
raise FileNotFoundError(f"Failed reading metadata from {metadata_file_name}") from exc
|
|
404
400
|
return _input_metadata
|
|
405
401
|
|
|
406
402
|
def _fill_product_meta(self, product_dict):
|
|
@@ -443,7 +439,7 @@ class MetadataCollector:
|
|
|
443
439
|
or self.args_dict.get("metadata_product_data_name")
|
|
444
440
|
or "undefined_model_name"
|
|
445
441
|
)
|
|
446
|
-
product_dict["data"]["model"]["version"] = self.schema_dict.get("
|
|
442
|
+
product_dict["data"]["model"]["version"] = self.schema_dict.get("schema_version", "0.0.0")
|
|
447
443
|
product_dict["data"]["model"]["type"] = self.schema_dict.get("meta_schema", None)
|
|
448
444
|
product_dict["data"]["model"]["url"] = self.schema_file or self.args_dict.get(
|
|
449
445
|
"metadata_product_data_url"
|
|
@@ -11,11 +11,14 @@ Follows CTAO top-level data model definition.
|
|
|
11
11
|
import logging
|
|
12
12
|
|
|
13
13
|
import simtools.data_model.schema
|
|
14
|
+
import simtools.utils.general as gen
|
|
14
15
|
|
|
15
16
|
_logger = logging.getLogger(__name__)
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
def get_default_metadata_dict(
|
|
19
|
+
def get_default_metadata_dict(
|
|
20
|
+
schema_file=None, observatory="CTA", schema_version="latest", lower_case=True
|
|
21
|
+
):
|
|
19
22
|
"""
|
|
20
23
|
Return metadata schema with default values.
|
|
21
24
|
|
|
@@ -27,6 +30,10 @@ def get_default_metadata_dict(schema_file=None, observatory="CTA"):
|
|
|
27
30
|
Schema file (jsonschema format) used for validation
|
|
28
31
|
observatory: str
|
|
29
32
|
Observatory name
|
|
33
|
+
schema_version: str, optional
|
|
34
|
+
Version of the schema to use. If not provided, the latest version is used.
|
|
35
|
+
lower_case: bool, optional
|
|
36
|
+
If True, all keys in the returned dictionary will be converted to lower case.
|
|
30
37
|
|
|
31
38
|
Returns
|
|
32
39
|
-------
|
|
@@ -35,8 +42,11 @@ def get_default_metadata_dict(schema_file=None, observatory="CTA"):
|
|
|
35
42
|
|
|
36
43
|
|
|
37
44
|
"""
|
|
38
|
-
schema = simtools.data_model.schema.load_schema(schema_file)
|
|
39
|
-
return
|
|
45
|
+
schema = simtools.data_model.schema.load_schema(schema_file, schema_version=schema_version)
|
|
46
|
+
return gen.change_dict_keys_case(
|
|
47
|
+
data_dict=_fill_defaults(schema["definitions"], observatory.lower()),
|
|
48
|
+
lower_case=lower_case,
|
|
49
|
+
)
|
|
40
50
|
|
|
41
51
|
|
|
42
52
|
def _resolve_references(yaml_data, observatory="CTA"):
|
|
@@ -62,7 +72,7 @@ def _resolve_references(yaml_data, observatory="CTA"):
|
|
|
62
72
|
parts = ref_path.split("/")
|
|
63
73
|
ref_data = yaml_data
|
|
64
74
|
for part in parts:
|
|
65
|
-
if part in ("definitions", observatory):
|
|
75
|
+
if part in ("definitions", observatory.lower()):
|
|
66
76
|
continue
|
|
67
77
|
ref_data = ref_data.get(part, {})
|
|
68
78
|
return ref_data
|
|
@@ -123,7 +133,7 @@ def _fill_defaults_recursive(sub_schema, current_dict):
|
|
|
123
133
|
Current dictionary to fill with default values.
|
|
124
134
|
"""
|
|
125
135
|
if "properties" not in sub_schema:
|
|
126
|
-
|
|
136
|
+
raise KeyError("Missing 'properties' key in schema.")
|
|
127
137
|
|
|
128
138
|
for prop, prop_schema in sub_schema["properties"].items():
|
|
129
139
|
_process_property(prop, prop_schema, current_dict)
|
|
@@ -152,10 +162,3 @@ def _process_property(prop, prop_schema, current_dict):
|
|
|
152
162
|
current_dict[prop] = [{}]
|
|
153
163
|
if "items" in prop_schema and isinstance(prop_schema["items"], dict):
|
|
154
164
|
_fill_defaults_recursive(prop_schema["items"], current_dict[prop][0])
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
def _raise_missing_properties_error():
|
|
158
|
-
"""Raise an error when the 'properties' key is missing in the schema."""
|
|
159
|
-
msg = "Missing 'properties' key in schema."
|
|
160
|
-
_logger.error(msg)
|
|
161
|
-
raise KeyError(msg)
|
|
@@ -1,40 +1,20 @@
|
|
|
1
1
|
"""Model data writer module."""
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
import logging
|
|
5
4
|
from pathlib import Path
|
|
6
5
|
|
|
7
|
-
import astropy.units as u
|
|
8
|
-
import numpy as np
|
|
9
6
|
from astropy.io.registry.base import IORegistryError
|
|
10
7
|
|
|
11
8
|
import simtools.utils.general as gen
|
|
12
9
|
from simtools.data_model import schema, validate_data
|
|
13
10
|
from simtools.data_model.metadata_collector import MetadataCollector
|
|
14
11
|
from simtools.db import db_handler
|
|
15
|
-
from simtools.
|
|
12
|
+
from simtools.io import ascii_handler, io_handler
|
|
16
13
|
from simtools.utils import names, value_conversion
|
|
17
14
|
|
|
18
15
|
__all__ = ["ModelDataWriter"]
|
|
19
16
|
|
|
20
17
|
|
|
21
|
-
class JsonNumpyEncoder(json.JSONEncoder):
|
|
22
|
-
"""Convert numpy to python types as accepted by json.dump."""
|
|
23
|
-
|
|
24
|
-
def default(self, o):
|
|
25
|
-
if isinstance(o, np.floating):
|
|
26
|
-
return float(o)
|
|
27
|
-
if isinstance(o, np.integer):
|
|
28
|
-
return int(o)
|
|
29
|
-
if isinstance(o, np.ndarray):
|
|
30
|
-
return o.tolist()
|
|
31
|
-
if isinstance(o, u.core.CompositeUnit | u.core.IrreducibleUnit | u.core.Unit):
|
|
32
|
-
return str(o) if o != u.dimensionless_unscaled else None
|
|
33
|
-
if np.issubdtype(type(o), np.bool_):
|
|
34
|
-
return bool(o)
|
|
35
|
-
return super().default(o)
|
|
36
|
-
|
|
37
|
-
|
|
38
18
|
class ModelDataWriter:
|
|
39
19
|
"""
|
|
40
20
|
Writer for simulation model data and metadata.
|
|
@@ -254,7 +234,7 @@ class ModelDataWriter:
|
|
|
254
234
|
"""
|
|
255
235
|
self._logger.debug(f"Getting validated parameter dictionary for {instrument}")
|
|
256
236
|
schema_file = schema.get_model_parameter_schema_file(parameter_name)
|
|
257
|
-
self.schema_dict =
|
|
237
|
+
self.schema_dict = ascii_handler.collect_data_from_file(schema_file)
|
|
258
238
|
|
|
259
239
|
value, unit = value_conversion.split_value_and_unit(value)
|
|
260
240
|
|
|
@@ -381,7 +361,7 @@ class ModelDataWriter:
|
|
|
381
361
|
|
|
382
362
|
if metadata is not None:
|
|
383
363
|
product_data.meta.update(
|
|
384
|
-
gen.change_dict_keys_case(metadata.get_top_level_metadata(),
|
|
364
|
+
gen.change_dict_keys_case(metadata.get_top_level_metadata(), True)
|
|
385
365
|
)
|
|
386
366
|
|
|
387
367
|
self._logger.info(f"Writing data to {self.product_data_file}")
|
|
@@ -415,15 +395,13 @@ class ModelDataWriter:
|
|
|
415
395
|
if data writing was not successful.
|
|
416
396
|
"""
|
|
417
397
|
data_dict = ModelDataWriter.prepare_data_dict_for_writing(data_dict)
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
f"Error writing model data to {self.io_handler.get_output_file(file_name)}"
|
|
426
|
-
) from exc
|
|
398
|
+
self._logger.info(f"Writing data to {self.io_handler.get_output_file(file_name)}")
|
|
399
|
+
ascii_handler.write_data_to_file(
|
|
400
|
+
data=data_dict,
|
|
401
|
+
output_file=self.io_handler.get_output_file(file_name),
|
|
402
|
+
sort_keys=False,
|
|
403
|
+
numpy_types=True,
|
|
404
|
+
)
|
|
427
405
|
|
|
428
406
|
@staticmethod
|
|
429
407
|
def prepare_data_dict_for_writing(data_dict):
|
|
@@ -432,6 +410,7 @@ class ModelDataWriter:
|
|
|
432
410
|
|
|
433
411
|
Ensure sim_telarray style lists as strings 'type' and 'unit' entries.
|
|
434
412
|
Replace "None" with "null" for unit field.
|
|
413
|
+
Replace list of equal units with single unit string.
|
|
435
414
|
|
|
436
415
|
Parameters
|
|
437
416
|
----------
|
|
@@ -452,6 +431,8 @@ class ModelDataWriter:
|
|
|
452
431
|
unit.replace("None", "null") if isinstance(unit, str) else unit
|
|
453
432
|
for unit in data_dict["unit"]
|
|
454
433
|
]
|
|
434
|
+
if all(u == data_dict["unit"][0] for u in data_dict["unit"]):
|
|
435
|
+
data_dict["unit"] = data_dict["unit"][0]
|
|
455
436
|
except KeyError:
|
|
456
437
|
pass
|
|
457
438
|
return data_dict
|
simtools/data_model/schema.py
CHANGED
|
@@ -14,6 +14,7 @@ from simtools.constants import (
|
|
|
14
14
|
SCHEMA_PATH,
|
|
15
15
|
)
|
|
16
16
|
from simtools.data_model import format_checkers
|
|
17
|
+
from simtools.io import ascii_handler
|
|
17
18
|
from simtools.utils import names
|
|
18
19
|
|
|
19
20
|
_logger = logging.getLogger(__name__)
|
|
@@ -37,7 +38,7 @@ def get_model_parameter_schema_files(schema_directory=MODEL_PARAMETER_SCHEMA_PAT
|
|
|
37
38
|
parameters = []
|
|
38
39
|
for schema_file in schema_files:
|
|
39
40
|
# reading parameter 'name' only - first document in schema file should be ok
|
|
40
|
-
schema_dict =
|
|
41
|
+
schema_dict = ascii_handler.collect_data_from_file(file_name=schema_file, yaml_document=0)
|
|
41
42
|
parameters.append(schema_dict.get("name"))
|
|
42
43
|
return parameters, schema_files
|
|
43
44
|
|
|
@@ -80,12 +81,12 @@ def get_model_parameter_schema_version(schema_version=None):
|
|
|
80
81
|
Schema version.
|
|
81
82
|
|
|
82
83
|
"""
|
|
83
|
-
schemas =
|
|
84
|
+
schemas = ascii_handler.collect_data_from_file(MODEL_PARAMETER_METASCHEMA)
|
|
84
85
|
|
|
85
86
|
if schema_version is None and schemas:
|
|
86
|
-
return schemas[0].get("
|
|
87
|
+
return schemas[0].get("schema_version")
|
|
87
88
|
|
|
88
|
-
if any(schema.get("
|
|
89
|
+
if any(schema.get("schema_version") == schema_version for schema in schemas):
|
|
89
90
|
return schema_version
|
|
90
91
|
|
|
91
92
|
raise ValueError(f"Schema version {schema_version} not found in {MODEL_PARAMETER_METASCHEMA}.")
|
|
@@ -112,13 +113,7 @@ def validate_dict_using_schema(data, schema_file=None, json_schema=None):
|
|
|
112
113
|
_logger.warning(f"No schema provided for validation of {data}")
|
|
113
114
|
return None
|
|
114
115
|
if json_schema is None:
|
|
115
|
-
json_schema = load_schema(
|
|
116
|
-
schema_file,
|
|
117
|
-
data.get("schema_version")
|
|
118
|
-
or data.get(
|
|
119
|
-
"SCHEMA_VERSION", "0.1.0"
|
|
120
|
-
), # default version to ensure backward compatibility
|
|
121
|
-
)
|
|
116
|
+
json_schema = load_schema(schema_file, get_schema_version_from_data(data))
|
|
122
117
|
|
|
123
118
|
validator = jsonschema.Draft6Validator(
|
|
124
119
|
schema=json_schema,
|
|
@@ -145,11 +140,36 @@ def validate_dict_using_schema(data, schema_file=None, json_schema=None):
|
|
|
145
140
|
def _retrieve_yaml_schema_from_uri(uri):
|
|
146
141
|
"""Load schema from a file URI."""
|
|
147
142
|
path = SCHEMA_PATH / Path(uri.removeprefix("file:/"))
|
|
148
|
-
contents =
|
|
143
|
+
contents = ascii_handler.collect_data_from_file(file_name=path)
|
|
149
144
|
return Resource.from_contents(contents)
|
|
150
145
|
|
|
151
146
|
|
|
152
|
-
def
|
|
147
|
+
def get_schema_version_from_data(data, observatory="cta"):
|
|
148
|
+
"""
|
|
149
|
+
Get schema version from data dictionary.
|
|
150
|
+
|
|
151
|
+
Parameters
|
|
152
|
+
----------
|
|
153
|
+
data: dict
|
|
154
|
+
data dictionary.
|
|
155
|
+
|
|
156
|
+
Returns
|
|
157
|
+
-------
|
|
158
|
+
str
|
|
159
|
+
Schema version. If not found, returns 'latest'.
|
|
160
|
+
"""
|
|
161
|
+
schema_version = data.get("schema_version") or data.get("SCHEMA_VERSION")
|
|
162
|
+
if schema_version:
|
|
163
|
+
return schema_version
|
|
164
|
+
reference_version = data.get(observatory.upper(), {}).get("REFERENCE", {}).get(
|
|
165
|
+
"VERSION"
|
|
166
|
+
) or data.get(observatory.lower(), {}).get("reference", {}).get("version")
|
|
167
|
+
if reference_version:
|
|
168
|
+
return reference_version
|
|
169
|
+
return "latest"
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def load_schema(schema_file=None, schema_version="latest"):
|
|
153
173
|
"""
|
|
154
174
|
Load parameter schema from file.
|
|
155
175
|
|
|
@@ -175,28 +195,58 @@ def load_schema(schema_file=None, schema_version=None):
|
|
|
175
195
|
|
|
176
196
|
for path in (schema_file, SCHEMA_PATH / schema_file):
|
|
177
197
|
try:
|
|
178
|
-
schema =
|
|
198
|
+
schema = ascii_handler.collect_data_from_file(file_name=path)
|
|
179
199
|
break
|
|
180
200
|
except FileNotFoundError:
|
|
181
201
|
continue
|
|
182
202
|
else:
|
|
183
203
|
raise FileNotFoundError(f"Schema file not found: {schema_file}")
|
|
184
204
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
raise ValueError(f"Schema version not given in {schema_file}.")
|
|
188
|
-
schema = next((doc for doc in schema if doc.get("version") == schema_version), None)
|
|
189
|
-
if schema is None:
|
|
190
|
-
raise ValueError(f"Schema version {schema_version} not found in {schema_file}.")
|
|
191
|
-
elif schema_version is not None and schema_version != schema.get("version"):
|
|
192
|
-
_logger.warning(f"Schema version {schema_version} does not match {schema.get('version')}")
|
|
193
|
-
|
|
194
|
-
_logger.debug(f"Loading schema from {schema_file}")
|
|
205
|
+
_logger.debug(f"Loading schema from {schema_file} for schema version {schema_version}")
|
|
206
|
+
schema = _get_schema_for_version(schema, schema_file, schema_version)
|
|
195
207
|
_add_array_elements("InstrumentTypeElement", schema)
|
|
196
208
|
|
|
197
209
|
return schema
|
|
198
210
|
|
|
199
211
|
|
|
212
|
+
def _get_schema_for_version(schema, schema_file, schema_version):
|
|
213
|
+
"""
|
|
214
|
+
Get schema for a specific version.
|
|
215
|
+
|
|
216
|
+
Allow for 'latest' version to return the most recent schema.
|
|
217
|
+
|
|
218
|
+
Parameters
|
|
219
|
+
----------
|
|
220
|
+
schema: dict or list
|
|
221
|
+
Schema dictionary or list of dictionaries.
|
|
222
|
+
schema_file: str
|
|
223
|
+
Path to schema file.
|
|
224
|
+
schema_version: str or None
|
|
225
|
+
Schema version to retrieve. If 'latest', the most recent version is returned.
|
|
226
|
+
|
|
227
|
+
Returns
|
|
228
|
+
-------
|
|
229
|
+
dict
|
|
230
|
+
Schema dictionary for the specified version.
|
|
231
|
+
"""
|
|
232
|
+
if schema_version is None:
|
|
233
|
+
raise ValueError(f"Schema version not given in {schema_file}.")
|
|
234
|
+
|
|
235
|
+
if isinstance(schema, list): # schema file with several schemas defined
|
|
236
|
+
if len(schema) == 0:
|
|
237
|
+
raise ValueError(f"No schemas found in {schema_file}.")
|
|
238
|
+
if schema_version == "latest":
|
|
239
|
+
schema_version = schema[0].get("schema_version")
|
|
240
|
+
schema = next((doc for doc in schema if doc.get("schema_version") == schema_version), None)
|
|
241
|
+
if schema is None:
|
|
242
|
+
raise ValueError(f"Schema version {schema_version} not found in {schema_file}.")
|
|
243
|
+
if schema_version not in (None, "latest") and schema_version != schema.get("schema_version"):
|
|
244
|
+
_logger.warning(
|
|
245
|
+
f"Schema version {schema_version} does not match {schema.get('schema_version')}"
|
|
246
|
+
)
|
|
247
|
+
return schema
|
|
248
|
+
|
|
249
|
+
|
|
200
250
|
def _get_array_element_list():
|
|
201
251
|
"""Build complete list of array elements including design types."""
|
|
202
252
|
elements = set(names.array_elements().keys())
|
|
@@ -12,6 +12,7 @@ from astropy.utils.diff import report_diff_values
|
|
|
12
12
|
|
|
13
13
|
import simtools.utils.general as gen
|
|
14
14
|
from simtools.data_model import schema
|
|
15
|
+
from simtools.io import ascii_handler
|
|
15
16
|
from simtools.utils import names, value_conversion
|
|
16
17
|
|
|
17
18
|
__all__ = ["DataValidator"]
|
|
@@ -100,7 +101,7 @@ class DataValidator:
|
|
|
100
101
|
"""
|
|
101
102
|
try:
|
|
102
103
|
if Path(self.data_file_name).suffix in (".yml", ".yaml", ".json"):
|
|
103
|
-
self.data_dict =
|
|
104
|
+
self.data_dict = ascii_handler.collect_data_from_file(self.data_file_name)
|
|
104
105
|
self._logger.info(f"Validating data from: {self.data_file_name}")
|
|
105
106
|
else:
|
|
106
107
|
self.data_table = Table.read(self.data_file_name, guess=True, delimiter=r"\s")
|
|
@@ -186,9 +187,14 @@ class DataValidator:
|
|
|
186
187
|
value_as_list, unit_as_list = self._get_value_and_units_as_lists()
|
|
187
188
|
|
|
188
189
|
for index, (value, unit) in enumerate(zip(value_as_list, unit_as_list)):
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
try:
|
|
191
|
+
value_as_list[index], unit_as_list[index] = self._validate_value_and_unit(
|
|
192
|
+
value, unit, index
|
|
193
|
+
)
|
|
194
|
+
except TypeError as ex:
|
|
195
|
+
raise TypeError(
|
|
196
|
+
f"Error validating dictionary using {self.schema_file_name}"
|
|
197
|
+
) from ex
|
|
192
198
|
|
|
193
199
|
if len(value_as_list) == 1:
|
|
194
200
|
self.data_dict["value"], self.data_dict["unit"] = value_as_list[0], unit_as_list[0]
|
|
@@ -563,7 +569,7 @@ class DataValidator:
|
|
|
563
569
|
If unit conversions fails
|
|
564
570
|
|
|
565
571
|
"""
|
|
566
|
-
self.
|
|
572
|
+
self._rate_limited_logger(col_name, f"Checking data column '{col_name}'")
|
|
567
573
|
|
|
568
574
|
reference_unit = self._get_reference_unit(col_name)
|
|
569
575
|
try:
|
|
@@ -574,9 +580,10 @@ class DataValidator:
|
|
|
574
580
|
if self._is_dimensionless(column_unit) and self._is_dimensionless(reference_unit):
|
|
575
581
|
return data, u.dimensionless_unscaled
|
|
576
582
|
|
|
577
|
-
self.
|
|
583
|
+
self._rate_limited_logger(
|
|
584
|
+
col_name,
|
|
578
585
|
f"Data column '{col_name}' with reference unit "
|
|
579
|
-
f"'{reference_unit}' and data unit '{column_unit}'"
|
|
586
|
+
f"'{reference_unit}' and data unit '{column_unit}'",
|
|
580
587
|
)
|
|
581
588
|
try:
|
|
582
589
|
if isinstance(data, u.Quantity | Column):
|
|
@@ -652,7 +659,9 @@ class DataValidator:
|
|
|
652
659
|
range columns
|
|
653
660
|
|
|
654
661
|
"""
|
|
655
|
-
self.
|
|
662
|
+
self._rate_limited_logger(
|
|
663
|
+
col_name, f"Checking data in column '{col_name}' for '{range_type}'"
|
|
664
|
+
)
|
|
656
665
|
|
|
657
666
|
if range_type not in ("allowed_range", "required_range"):
|
|
658
667
|
raise KeyError("Allowed range types are 'allowed_range', 'required_range'")
|
|
@@ -673,6 +682,26 @@ class DataValidator:
|
|
|
673
682
|
f"{_entry[range_type].get('max', np.inf)}])"
|
|
674
683
|
)
|
|
675
684
|
|
|
685
|
+
def _rate_limited_logger(self, col_name, message, max_logs=10):
|
|
686
|
+
"""
|
|
687
|
+
Log debug messages at a limited rate defined by a numerical column name.
|
|
688
|
+
|
|
689
|
+
Parameters
|
|
690
|
+
----------
|
|
691
|
+
col_name: str or int
|
|
692
|
+
Column name or index to limit the rate of logging.
|
|
693
|
+
message: str
|
|
694
|
+
Message to log.
|
|
695
|
+
max_logs: int
|
|
696
|
+
Maximum number of logging messages to be printed.
|
|
697
|
+
"""
|
|
698
|
+
try:
|
|
699
|
+
col_index = int(col_name)
|
|
700
|
+
if col_index < max_logs:
|
|
701
|
+
self._logger.debug(message)
|
|
702
|
+
except (ValueError, TypeError):
|
|
703
|
+
self._logger.debug(message)
|
|
704
|
+
|
|
676
705
|
@staticmethod
|
|
677
706
|
def _interval_check(data, axis_range, range_type):
|
|
678
707
|
"""
|
|
@@ -732,11 +761,11 @@ class DataValidator:
|
|
|
732
761
|
ValueError
|
|
733
762
|
if schema version is not found in schema file
|
|
734
763
|
"""
|
|
735
|
-
schema_data =
|
|
764
|
+
schema_data = ascii_handler.collect_data_from_file(file_name=schema_file)
|
|
736
765
|
entries = schema_data if isinstance(schema_data, list) else [schema_data]
|
|
737
766
|
|
|
738
767
|
for entry in entries:
|
|
739
|
-
if not schema_version or entry.get("
|
|
768
|
+
if not schema_version or entry.get("schema_version") == schema_version:
|
|
740
769
|
try:
|
|
741
770
|
return entry["data"]
|
|
742
771
|
except KeyError as exc:
|
|
@@ -774,8 +803,9 @@ class DataValidator:
|
|
|
774
803
|
If data column is not found.
|
|
775
804
|
|
|
776
805
|
"""
|
|
777
|
-
self.
|
|
778
|
-
|
|
806
|
+
self._rate_limited_logger(
|
|
807
|
+
column_name,
|
|
808
|
+
f"Getting reference data column {column_name} from schema {self._data_description}",
|
|
779
809
|
)
|
|
780
810
|
try:
|
|
781
811
|
return (
|