gammasimtools 0.17.0__py3-none-any.whl → 0.19.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gammasimtools-0.17.0.dist-info → gammasimtools-0.19.0.dist-info}/METADATA +27 -69
- gammasimtools-0.19.0.dist-info/RECORD +393 -0
- {gammasimtools-0.17.0.dist-info → gammasimtools-0.19.0.dist-info}/entry_points.txt +10 -2
- {gammasimtools-0.17.0.dist-info → gammasimtools-0.19.0.dist-info}/licenses/LICENSE +1 -1
- simtools/_version.py +16 -3
- simtools/applications/calculate_trigger_rate.py +1 -1
- simtools/applications/convert_all_model_parameters_from_simtel.py +4 -3
- simtools/applications/convert_geo_coordinates_of_array_elements.py +3 -3
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +10 -1
- simtools/applications/db_add_value_from_json_to_db.py +2 -1
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +8 -13
- simtools/applications/db_generate_compound_indexes.py +61 -0
- simtools/applications/db_get_file_from_db.py +1 -1
- simtools/applications/db_get_parameter_from_db.py +4 -4
- simtools/applications/db_inspect_databases.py +20 -10
- simtools/applications/derive_mirror_rnda.py +18 -12
- simtools/applications/derive_psf_parameters.py +59 -309
- simtools/applications/docs_produce_array_element_report.py +1 -1
- simtools/applications/docs_produce_calibration_reports.py +1 -1
- simtools/applications/docs_produce_model_parameter_reports.py +1 -1
- simtools/applications/docs_produce_simulation_configuration_report.py +1 -1
- simtools/applications/generate_corsika_histograms.py +1 -1
- simtools/applications/generate_default_metadata.py +8 -24
- simtools/applications/generate_sim_telarray_histograms.py +1 -1
- simtools/applications/generate_simtel_event_data.py +97 -5
- simtools/applications/maintain_simulation_model_add_production_table.py +71 -0
- simtools/applications/maintain_simulation_model_compare_productions.py +98 -0
- simtools/applications/{verify_simulation_model_production_tables.py → maintain_simulation_model_verify_production_tables.py} +9 -1
- simtools/applications/merge_tables.py +16 -18
- simtools/applications/plot_array_layout.py +3 -3
- simtools/applications/plot_simtel_events.py +379 -0
- simtools/applications/plot_tabular_data.py +21 -3
- simtools/applications/plot_tabular_data_for_model_parameter.py +104 -0
- simtools/applications/print_version.py +8 -9
- simtools/applications/production_derive_corsika_limits.py +64 -27
- simtools/applications/production_derive_statistics.py +1 -1
- simtools/applications/production_generate_grid.py +2 -2
- simtools/applications/production_merge_corsika_limits.py +214 -0
- simtools/applications/run_application.py +47 -113
- simtools/applications/simulate_calibration_events.py +166 -0
- simtools/applications/simulate_flasher.py +141 -0
- simtools/applications/{simulate_light_emission.py → simulate_illuminator.py} +35 -99
- simtools/applications/simulate_prod.py +6 -24
- simtools/applications/simulate_prod_htcondor_generator.py +7 -0
- simtools/applications/submit_array_layouts.py +2 -1
- simtools/applications/submit_model_parameter_from_external.py +1 -1
- simtools/applications/validate_camera_efficiency.py +30 -12
- simtools/applications/validate_camera_fov.py +1 -1
- simtools/applications/validate_cumulative_psf.py +1 -1
- simtools/applications/validate_file_using_schema.py +2 -1
- simtools/applications/validate_optics.py +1 -1
- simtools/camera/camera_efficiency.py +61 -45
- simtools/camera/single_photon_electron_spectrum.py +1 -1
- simtools/configuration/commandline_parser.py +31 -1
- simtools/configuration/configurator.py +4 -4
- simtools/constants.py +2 -0
- simtools/corsika/corsika_config.py +45 -25
- simtools/corsika/corsika_histograms.py +6 -5
- simtools/data_model/data_reader.py +2 -3
- simtools/data_model/metadata_collector.py +32 -36
- simtools/data_model/metadata_model.py +15 -12
- simtools/data_model/model_data_writer.py +13 -32
- simtools/data_model/schema.py +88 -24
- simtools/data_model/validate_data.py +34 -9
- simtools/db/db_handler.py +48 -37
- simtools/db/db_model_upload.py +3 -3
- simtools/dependencies.py +88 -25
- simtools/io/ascii_handler.py +279 -0
- simtools/{io_operations → io}/io_handler.py +25 -3
- simtools/{io_operations/io_table_handler.py → io/table_handler.py} +1 -1
- simtools/job_execution/htcondor_script_generator.py +15 -4
- simtools/layout/array_layout.py +1 -1
- simtools/layout/array_layout_utils.py +19 -8
- simtools/model/array_model.py +28 -5
- simtools/model/flasher_model.py +106 -0
- simtools/model/model_parameter.py +4 -4
- simtools/model/model_repository.py +197 -2
- simtools/model/telescope_model.py +3 -1
- simtools/production_configuration/derive_corsika_limits.py +361 -427
- simtools/production_configuration/derive_production_statistics_handler.py +7 -6
- simtools/production_configuration/generate_production_grid.py +9 -11
- simtools/production_configuration/merge_corsika_limits.py +528 -0
- simtools/ray_tracing/mirror_panel_psf.py +1 -0
- simtools/ray_tracing/psf_parameter_optimisation.py +792 -0
- simtools/ray_tracing/ray_tracing.py +6 -2
- simtools/reporting/docs_read_parameters.py +150 -62
- simtools/resources/array-element-ids.json +126 -0
- simtools/runners/corsika_runner.py +1 -1
- simtools/runners/corsika_simtel_runner.py +14 -5
- simtools/runners/runner_services.py +10 -5
- simtools/runners/simtools_runner.py +267 -0
- simtools/schemas/application_workflow.metaschema.yml +101 -68
- simtools/schemas/input/MST_mirror_2f_measurements.schema.yml +1 -1
- simtools/schemas/input/single_pe_spectrum.schema.yml +1 -1
- simtools/schemas/metadata.metaschema.yml +577 -3
- simtools/schemas/model_parameter.metaschema.yml +6 -6
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +7 -3
- simtools/schemas/model_parameters/adjust_gain.schema.yml +1 -1
- simtools/schemas/model_parameters/altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/array_coordinates.schema.yml +1 -1
- simtools/schemas/model_parameters/array_coordinates_UTM.schema.yml +1 -1
- simtools/schemas/model_parameters/array_element_position_ground.schema.yml +1 -1
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +1 -1
- simtools/schemas/model_parameters/array_layouts.schema.yml +1 -1
- simtools/schemas/model_parameters/array_triggers.schema.yml +1 -1
- simtools/schemas/model_parameters/array_window.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_shaping.schema.yml +1 -1
- simtools/schemas/model_parameters/asum_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/atmospheric_profile.schema.yml +42 -1
- simtools/schemas/model_parameters/atmospheric_transmission.schema.yml +44 -1
- simtools/schemas/model_parameters/axes_offsets.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_body_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_body_shape.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_config_file.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_config_rotate.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_depth.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_filter.schema.yml +11 -1
- simtools/schemas/model_parameters/camera_filter_incidence_angle.schema.yml +11 -1
- simtools/schemas/model_parameters/camera_pixels.schema.yml +1 -1
- simtools/schemas/model_parameters/camera_transmission.schema.yml +1 -1
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +1 -1
- simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_cherenkov_photon_bunch_size.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_cherenkov_photon_wavelength_range.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_first_interaction_height.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_longitudinal_shower_development.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_observation_level.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_particle_kinetic_energy_cutoff.schema.yml +1 -1
- simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +3 -3
- simtools/schemas/model_parameters/dark_events.schema.yml +1 -1
- simtools/schemas/model_parameters/default_trigger.schema.yml +1 -1
- simtools/schemas/model_parameters/design_model.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_ac_coupled.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/disc_start.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +32 -1
- simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/dish_shape_length.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_pedsub.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +1 -1
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +2 -2
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +1 -1
- simtools/schemas/model_parameters/effective_focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/epsg_code.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_ac_coupled.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_long_event_threshold.schema.yml +35 -0
- simtools/schemas/model_parameters/fadc_long_sum_bins.schema.yml +41 -0
- simtools/schemas/model_parameters/fadc_long_sum_offset.schema.yml +38 -0
- simtools/schemas/model_parameters/fadc_max_signal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_max_sum.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_mhz.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_noise.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +13 -1
- simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +1 -1
- simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +1 -1
- simtools/schemas/model_parameters/fake_mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/flatfielding.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_surface_parameters.schema.yml +1 -1
- simtools/schemas/model_parameters/focal_surface_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/focus_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/gain_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_horizontal.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_rotation.schema.yml +1 -1
- simtools/schemas/model_parameters/geomag_vertical.schema.yml +1 -1
- simtools/schemas/model_parameters/hg_lg_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_events.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_external_trigger.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_exptime.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_sigtime.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_pulse_twidth.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_var_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/laser_wavelength.schema.yml +1 -1
- simtools/schemas/model_parameters/led_events.schema.yml +1 -1
- simtools/schemas/model_parameters/led_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/led_pulse_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/led_pulse_sigtime.schema.yml +1 -1
- simtools/schemas/model_parameters/led_var_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +11 -1
- simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +50 -1
- simtools/schemas/model_parameters/min_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/min_photons.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_class.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_list.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_panel_2f_measurements.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +11 -1
- simtools/schemas/model_parameters/multiplicity_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/muon_mono_threshold.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_gain_drop_scale.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_offaxis.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +13 -1
- simtools/schemas/model_parameters/nsb_reference_value.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_scaling_factor.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_sky_map.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_spectrum.schema.yml +1 -1
- simtools/schemas/model_parameters/num_gains.schema.yml +1 -1
- simtools/schemas/model_parameters/only_triggered_telescopes.schema.yml +1 -1
- simtools/schemas/model_parameters/optics_properties.schema.yml +1 -1
- simtools/schemas/model_parameters/parabolic_dish.schema.yml +1 -1
- simtools/schemas/model_parameters/pedestal_events.schema.yml +1 -1
- simtools/schemas/model_parameters/photon_delay.schema.yml +1 -1
- simtools/schemas/model_parameters/photons_per_run.schema.yml +1 -1
- simtools/schemas/model_parameters/pixel_cells.schema.yml +1 -1
- simtools/schemas/model_parameters/pixels_parallel.schema.yml +1 -1
- simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_average_gain.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_gain_index.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +20 -1
- simtools/schemas/model_parameters/pm_transit_time.schema.yml +1 -1
- simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_hole_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_incidence_angle.schema.yml +11 -1
- simtools/schemas/model_parameters/primary_mirror_parameters.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/primary_mirror_segmentation.schema.yml +1 -1
- simtools/schemas/model_parameters/qe_variation.schema.yml +1 -1
- simtools/schemas/model_parameters/quantum_efficiency.schema.yml +11 -1
- simtools/schemas/model_parameters/random_focal_length.schema.yml +1 -1
- simtools/schemas/model_parameters/random_generator.schema.yml +1 -1
- simtools/schemas/model_parameters/random_mono_probability.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_altitude.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_latitude.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_longitude.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_utm_east.schema.yml +1 -1
- simtools/schemas/model_parameters/reference_point_utm_north.schema.yml +1 -1
- simtools/schemas/model_parameters/sampled_output.schema.yml +1 -1
- simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_baffle.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_map.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_hole_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_incidence_angle.schema.yml +11 -1
- simtools/schemas/model_parameters/secondary_mirror_parameters.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_ref_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_reflectivity.schema.yml +11 -1
- simtools/schemas/model_parameters/secondary_mirror_segmentation.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_shadow_diameter.schema.yml +1 -1
- simtools/schemas/model_parameters/secondary_mirror_shadow_offset.schema.yml +1 -1
- simtools/schemas/model_parameters/stars.schema.yml +1 -1
- simtools/schemas/model_parameters/store_photoelectrons.schema.yml +1 -1
- simtools/schemas/model_parameters/tailcut_scale.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_axis_height.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_random_angle.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_random_error.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +1 -1
- simtools/schemas/model_parameters/telescope_transmission.schema.yml +1 -1
- simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +1 -1
- simtools/schemas/model_parameters/teltrig_min_time.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_error.schema.yml +1 -1
- simtools/schemas/model_parameters/transit_time_jitter.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_current_limit.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +1 -1
- simtools/schemas/model_parameters/trigger_pixels.schema.yml +1 -1
- simtools/schemas/plot_configuration.metaschema.yml +51 -59
- simtools/schemas/production_configuration_metrics.schema.yml +12 -2
- simtools/schemas/production_tables.schema.yml +2 -2
- simtools/simtel/simtel_config_reader.py +2 -2
- simtools/simtel/simtel_config_writer.py +16 -4
- simtools/simtel/simtel_io_event_histograms.py +746 -0
- simtools/simtel/simtel_io_event_reader.py +16 -43
- simtools/simtel/simtel_io_event_writer.py +46 -10
- simtools/simtel/simtel_io_histogram.py +3 -1
- simtools/simtel/simtel_io_histograms.py +7 -3
- simtools/simtel/simtel_io_metadata.py +99 -3
- simtools/simtel/simtel_table_reader.py +92 -10
- simtools/simtel/simulator_array.py +138 -10
- simtools/simtel/simulator_camera_efficiency.py +32 -23
- simtools/simtel/simulator_light_emission.py +437 -271
- simtools/simtel/simulator_ray_tracing.py +1 -1
- simtools/simulator.py +105 -147
- simtools/testing/configuration.py +24 -26
- simtools/testing/helpers.py +2 -2
- simtools/testing/log_inspector.py +50 -0
- simtools/testing/validate_output.py +87 -37
- simtools/utils/general.py +125 -257
- simtools/utils/geometry.py +36 -0
- simtools/utils/names.py +72 -3
- simtools/visualization/legend_handlers.py +180 -264
- simtools/visualization/plot_array_layout.py +20 -8
- simtools/visualization/plot_pixels.py +1 -2
- simtools/visualization/plot_tables.py +202 -27
- simtools/visualization/simtel_event_plots.py +816 -0
- simtools/visualization/visualize.py +4 -101
- gammasimtools-0.17.0.dist-info/RECORD +0 -374
- simtools/production_configuration/derive_corsika_limits_grid.py +0 -189
- {gammasimtools-0.17.0.dist-info → gammasimtools-0.19.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.17.0.dist-info → gammasimtools-0.19.0.dist-info}/top_level.txt +0 -0
- /simtools/{io_operations → io}/hdf5_handler.py +0 -0
- /simtools/{io_operations → io}/legacy_data_handler.py +0 -0
- /simtools/{schemas → resources}/array_elements.yml +0 -0
|
@@ -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
|
@@ -4,6 +4,7 @@ import logging
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
6
|
import jsonschema
|
|
7
|
+
from referencing import Registry, Resource
|
|
7
8
|
|
|
8
9
|
import simtools.utils.general as gen
|
|
9
10
|
from simtools.constants import (
|
|
@@ -13,6 +14,7 @@ from simtools.constants import (
|
|
|
13
14
|
SCHEMA_PATH,
|
|
14
15
|
)
|
|
15
16
|
from simtools.data_model import format_checkers
|
|
17
|
+
from simtools.io import ascii_handler
|
|
16
18
|
from simtools.utils import names
|
|
17
19
|
|
|
18
20
|
_logger = logging.getLogger(__name__)
|
|
@@ -36,7 +38,7 @@ def get_model_parameter_schema_files(schema_directory=MODEL_PARAMETER_SCHEMA_PAT
|
|
|
36
38
|
parameters = []
|
|
37
39
|
for schema_file in schema_files:
|
|
38
40
|
# reading parameter 'name' only - first document in schema file should be ok
|
|
39
|
-
schema_dict =
|
|
41
|
+
schema_dict = ascii_handler.collect_data_from_file(file_name=schema_file, yaml_document=0)
|
|
40
42
|
parameters.append(schema_dict.get("name"))
|
|
41
43
|
return parameters, schema_files
|
|
42
44
|
|
|
@@ -79,12 +81,12 @@ def get_model_parameter_schema_version(schema_version=None):
|
|
|
79
81
|
Schema version.
|
|
80
82
|
|
|
81
83
|
"""
|
|
82
|
-
schemas =
|
|
84
|
+
schemas = ascii_handler.collect_data_from_file(MODEL_PARAMETER_METASCHEMA)
|
|
83
85
|
|
|
84
86
|
if schema_version is None and schemas:
|
|
85
|
-
return schemas[0].get("
|
|
87
|
+
return schemas[0].get("schema_version")
|
|
86
88
|
|
|
87
|
-
if any(schema.get("
|
|
89
|
+
if any(schema.get("schema_version") == schema_version for schema in schemas):
|
|
88
90
|
return schema_version
|
|
89
91
|
|
|
90
92
|
raise ValueError(f"Schema version {schema_version} not found in {MODEL_PARAMETER_METASCHEMA}.")
|
|
@@ -111,16 +113,16 @@ def validate_dict_using_schema(data, schema_file=None, json_schema=None):
|
|
|
111
113
|
_logger.warning(f"No schema provided for validation of {data}")
|
|
112
114
|
return None
|
|
113
115
|
if json_schema is None:
|
|
114
|
-
json_schema = load_schema(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
json_schema = load_schema(schema_file, get_schema_version_from_data(data))
|
|
117
|
+
|
|
118
|
+
validator = jsonschema.Draft6Validator(
|
|
119
|
+
schema=json_schema,
|
|
120
|
+
format_checker=format_checkers.format_checker,
|
|
121
|
+
registry=Registry(retrieve=_retrieve_yaml_schema_from_uri),
|
|
122
|
+
)
|
|
121
123
|
|
|
122
124
|
try:
|
|
123
|
-
|
|
125
|
+
validator.validate(instance=data)
|
|
124
126
|
except jsonschema.exceptions.ValidationError as exc:
|
|
125
127
|
_logger.error(f"Validation failed using schema: {json_schema} for data: {data}")
|
|
126
128
|
raise exc
|
|
@@ -135,7 +137,39 @@ def validate_dict_using_schema(data, schema_file=None, json_schema=None):
|
|
|
135
137
|
return data
|
|
136
138
|
|
|
137
139
|
|
|
138
|
-
def
|
|
140
|
+
def _retrieve_yaml_schema_from_uri(uri):
|
|
141
|
+
"""Load schema from a file URI."""
|
|
142
|
+
path = SCHEMA_PATH / Path(uri.removeprefix("file:/"))
|
|
143
|
+
contents = ascii_handler.collect_data_from_file(file_name=path)
|
|
144
|
+
return Resource.from_contents(contents)
|
|
145
|
+
|
|
146
|
+
|
|
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"):
|
|
139
173
|
"""
|
|
140
174
|
Load parameter schema from file.
|
|
141
175
|
|
|
@@ -161,28 +195,58 @@ def load_schema(schema_file=None, schema_version=None):
|
|
|
161
195
|
|
|
162
196
|
for path in (schema_file, SCHEMA_PATH / schema_file):
|
|
163
197
|
try:
|
|
164
|
-
schema =
|
|
198
|
+
schema = ascii_handler.collect_data_from_file(file_name=path)
|
|
165
199
|
break
|
|
166
200
|
except FileNotFoundError:
|
|
167
201
|
continue
|
|
168
202
|
else:
|
|
169
203
|
raise FileNotFoundError(f"Schema file not found: {schema_file}")
|
|
170
204
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
raise ValueError(f"Schema version not given in {schema_file}.")
|
|
174
|
-
schema = next((doc for doc in schema if doc.get("version") == schema_version), None)
|
|
175
|
-
if schema is None:
|
|
176
|
-
raise ValueError(f"Schema version {schema_version} not found in {schema_file}.")
|
|
177
|
-
elif schema_version is not None and schema_version != schema.get("version"):
|
|
178
|
-
_logger.warning(f"Schema version {schema_version} does not match {schema.get('version')}")
|
|
179
|
-
|
|
180
|
-
_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)
|
|
181
207
|
_add_array_elements("InstrumentTypeElement", schema)
|
|
182
208
|
|
|
183
209
|
return schema
|
|
184
210
|
|
|
185
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
|
+
|
|
186
250
|
def _get_array_element_list():
|
|
187
251
|
"""Build complete list of array elements including design types."""
|
|
188
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")
|
|
@@ -563,7 +564,7 @@ class DataValidator:
|
|
|
563
564
|
If unit conversions fails
|
|
564
565
|
|
|
565
566
|
"""
|
|
566
|
-
self.
|
|
567
|
+
self._rate_limited_logger(col_name, f"Checking data column '{col_name}'")
|
|
567
568
|
|
|
568
569
|
reference_unit = self._get_reference_unit(col_name)
|
|
569
570
|
try:
|
|
@@ -574,9 +575,10 @@ class DataValidator:
|
|
|
574
575
|
if self._is_dimensionless(column_unit) and self._is_dimensionless(reference_unit):
|
|
575
576
|
return data, u.dimensionless_unscaled
|
|
576
577
|
|
|
577
|
-
self.
|
|
578
|
+
self._rate_limited_logger(
|
|
579
|
+
col_name,
|
|
578
580
|
f"Data column '{col_name}' with reference unit "
|
|
579
|
-
f"'{reference_unit}' and data unit '{column_unit}'"
|
|
581
|
+
f"'{reference_unit}' and data unit '{column_unit}'",
|
|
580
582
|
)
|
|
581
583
|
try:
|
|
582
584
|
if isinstance(data, u.Quantity | Column):
|
|
@@ -652,7 +654,9 @@ class DataValidator:
|
|
|
652
654
|
range columns
|
|
653
655
|
|
|
654
656
|
"""
|
|
655
|
-
self.
|
|
657
|
+
self._rate_limited_logger(
|
|
658
|
+
col_name, f"Checking data in column '{col_name}' for '{range_type}'"
|
|
659
|
+
)
|
|
656
660
|
|
|
657
661
|
if range_type not in ("allowed_range", "required_range"):
|
|
658
662
|
raise KeyError("Allowed range types are 'allowed_range', 'required_range'")
|
|
@@ -673,6 +677,26 @@ class DataValidator:
|
|
|
673
677
|
f"{_entry[range_type].get('max', np.inf)}])"
|
|
674
678
|
)
|
|
675
679
|
|
|
680
|
+
def _rate_limited_logger(self, col_name, message, max_logs=10):
|
|
681
|
+
"""
|
|
682
|
+
Log debug messages at a limited rate defined by a numerical column name.
|
|
683
|
+
|
|
684
|
+
Parameters
|
|
685
|
+
----------
|
|
686
|
+
col_name: str or int
|
|
687
|
+
Column name or index to limit the rate of logging.
|
|
688
|
+
message: str
|
|
689
|
+
Message to log.
|
|
690
|
+
max_logs: int
|
|
691
|
+
Maximum number of logging messages to be printed.
|
|
692
|
+
"""
|
|
693
|
+
try:
|
|
694
|
+
col_index = int(col_name)
|
|
695
|
+
if col_index < max_logs:
|
|
696
|
+
self._logger.debug(message)
|
|
697
|
+
except (ValueError, TypeError):
|
|
698
|
+
self._logger.debug(message)
|
|
699
|
+
|
|
676
700
|
@staticmethod
|
|
677
701
|
def _interval_check(data, axis_range, range_type):
|
|
678
702
|
"""
|
|
@@ -732,11 +756,11 @@ class DataValidator:
|
|
|
732
756
|
ValueError
|
|
733
757
|
if schema version is not found in schema file
|
|
734
758
|
"""
|
|
735
|
-
schema_data =
|
|
759
|
+
schema_data = ascii_handler.collect_data_from_file(file_name=schema_file)
|
|
736
760
|
entries = schema_data if isinstance(schema_data, list) else [schema_data]
|
|
737
761
|
|
|
738
762
|
for entry in entries:
|
|
739
|
-
if not schema_version or entry.get("
|
|
763
|
+
if not schema_version or entry.get("schema_version") == schema_version:
|
|
740
764
|
try:
|
|
741
765
|
return entry["data"]
|
|
742
766
|
except KeyError as exc:
|
|
@@ -774,8 +798,9 @@ class DataValidator:
|
|
|
774
798
|
If data column is not found.
|
|
775
799
|
|
|
776
800
|
"""
|
|
777
|
-
self.
|
|
778
|
-
|
|
801
|
+
self._rate_limited_logger(
|
|
802
|
+
column_name,
|
|
803
|
+
f"Getting reference data column {column_name} from schema {self._data_description}",
|
|
779
804
|
)
|
|
780
805
|
try:
|
|
781
806
|
return (
|