gammasimtools 0.6.1__py3-none-any.whl → 0.8.1__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.8.1.dist-info/METADATA +172 -0
- gammasimtools-0.8.1.dist-info/RECORD +346 -0
- {gammasimtools-0.6.1.dist-info → gammasimtools-0.8.1.dist-info}/WHEEL +1 -1
- gammasimtools-0.8.1.dist-info/entry_points.txt +31 -0
- simtools/_version.py +2 -2
- simtools/applications/calculate_trigger_rate.py +210 -0
- simtools/applications/convert_all_model_parameters_from_simtel.py +372 -0
- simtools/applications/{print_array_elements.py → convert_geo_coordinates_of_array_elements.py} +58 -63
- simtools/applications/convert_model_parameter_from_simtel.py +119 -0
- simtools/applications/{add_file_to_db.py → db_add_file_to_db.py} +70 -60
- simtools/applications/db_add_model_parameters_from_repository_to_db.py +184 -0
- simtools/applications/db_add_value_from_json_to_db.py +105 -0
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +180 -0
- simtools/applications/db_get_array_layouts_from_db.py +162 -0
- simtools/applications/{get_file_from_db.py → db_get_file_from_db.py} +30 -34
- simtools/applications/db_get_parameter_from_db.py +131 -0
- simtools/applications/db_inspect_databases.py +52 -0
- simtools/applications/derive_mirror_rnda.py +39 -255
- simtools/applications/derive_psf_parameters.py +441 -0
- simtools/applications/generate_array_config.py +82 -0
- simtools/applications/generate_corsika_histograms.py +52 -52
- simtools/applications/generate_default_metadata.py +5 -8
- simtools/applications/generate_regular_arrays.py +117 -0
- simtools/applications/generate_simtel_array_histograms.py +97 -56
- simtools/applications/plot_array_layout.py +345 -115
- simtools/applications/production_generate_simulation_config.py +158 -0
- simtools/applications/production_scale_events.py +168 -0
- simtools/applications/simulate_light_emission.py +478 -0
- simtools/applications/simulate_prod.py +97 -175
- simtools/applications/submit_data_from_external.py +9 -12
- simtools/applications/submit_model_parameter_from_external.py +122 -0
- simtools/applications/validate_camera_efficiency.py +35 -102
- simtools/applications/validate_camera_fov.py +20 -19
- simtools/applications/{compare_cumulative_psf.py → validate_cumulative_psf.py} +45 -44
- simtools/applications/validate_file_using_schema.py +113 -47
- simtools/applications/validate_optics.py +17 -22
- simtools/camera_efficiency.py +193 -202
- simtools/configuration/commandline_parser.py +384 -96
- simtools/configuration/configurator.py +55 -71
- simtools/constants.py +5 -5
- simtools/corsika/corsika_config.py +482 -342
- simtools/corsika/corsika_histograms.py +226 -204
- simtools/corsika/corsika_histograms_visualize.py +23 -24
- simtools/corsika/primary_particle.py +159 -0
- simtools/data_model/data_reader.py +25 -20
- simtools/data_model/format_checkers.py +52 -0
- simtools/data_model/metadata_collector.py +210 -184
- simtools/data_model/metadata_model.py +115 -37
- simtools/data_model/model_data_writer.py +335 -26
- simtools/data_model/validate_data.py +366 -154
- simtools/db/db_array_elements.py +130 -0
- simtools/db/db_from_repo_handler.py +106 -0
- simtools/db/db_handler.py +1246 -0
- simtools/io_operations/hdf5_handler.py +3 -1
- simtools/io_operations/io_handler.py +32 -57
- simtools/job_execution/job_manager.py +82 -69
- simtools/layout/array_layout.py +325 -537
- simtools/layout/geo_coordinates.py +8 -11
- simtools/layout/telescope_position.py +163 -86
- simtools/model/array_model.py +305 -256
- simtools/model/calibration_model.py +50 -0
- simtools/model/camera.py +233 -493
- simtools/model/mirrors.py +61 -44
- simtools/model/model_parameter.py +602 -0
- simtools/model/model_utils.py +7 -35
- simtools/model/site_model.py +161 -0
- simtools/model/telescope_model.py +127 -621
- simtools/production_configuration/calculate_statistical_errors_grid_point.py +454 -0
- simtools/production_configuration/event_scaler.py +146 -0
- simtools/production_configuration/generate_simulation_config.py +193 -0
- simtools/production_configuration/interpolation_handler.py +197 -0
- simtools/ray_tracing/__init__.py +0 -0
- simtools/ray_tracing/mirror_panel_psf.py +280 -0
- simtools/{psf_analysis.py → ray_tracing/psf_analysis.py} +133 -47
- simtools/ray_tracing/ray_tracing.py +646 -0
- simtools/runners/__init__.py +0 -0
- simtools/runners/corsika_runner.py +240 -0
- simtools/runners/corsika_simtel_runner.py +225 -0
- simtools/runners/runner_services.py +307 -0
- simtools/runners/simtel_runner.py +224 -0
- simtools/schemas/array_elements.yml +137 -0
- simtools/schemas/integration_tests_config.metaschema.yml +93 -0
- simtools/schemas/metadata.metaschema.yml +6 -0
- simtools/schemas/model_parameter.metaschema.yml +78 -0
- simtools/schemas/{data.metaschema.yml → model_parameter_and_data_schema.metaschema.yml} +27 -44
- simtools/schemas/model_parameters/adjust_gain.schema.yml +37 -0
- simtools/schemas/model_parameters/altitude.schema.yml +37 -0
- simtools/schemas/model_parameters/array_coordinates.schema.yml +33 -0
- simtools/schemas/model_parameters/array_coordinates_UTM.schema.yml +77 -0
- simtools/schemas/model_parameters/array_element_position_ground.schema.yml +39 -0
- simtools/schemas/model_parameters/array_element_position_utm.schema.yml +39 -0
- simtools/schemas/model_parameters/array_layouts.schema.yml +48 -0
- simtools/schemas/model_parameters/array_triggers.schema.yml +93 -0
- simtools/schemas/model_parameters/asum_clipping.schema.yml +38 -0
- simtools/schemas/model_parameters/asum_offset.schema.yml +35 -0
- simtools/schemas/model_parameters/asum_shaping.schema.yml +35 -0
- simtools/schemas/model_parameters/asum_threshold.schema.yml +38 -0
- simtools/schemas/model_parameters/atmospheric_profile.schema.yml +32 -0
- simtools/schemas/model_parameters/atmospheric_transmission.schema.yml +35 -0
- simtools/schemas/model_parameters/axes_offsets.schema.yml +53 -0
- simtools/schemas/model_parameters/camera_body_diameter.schema.yml +40 -0
- simtools/schemas/model_parameters/camera_body_shape.schema.yml +45 -0
- simtools/schemas/model_parameters/camera_config_file.schema.yml +40 -0
- simtools/schemas/model_parameters/camera_config_rotate.schema.yml +36 -0
- simtools/schemas/model_parameters/camera_degraded_efficiency.schema.yml +43 -0
- simtools/schemas/model_parameters/camera_degraded_map.schema.yml +42 -0
- simtools/schemas/model_parameters/camera_depth.schema.yml +42 -0
- simtools/schemas/model_parameters/camera_filter.schema.yml +45 -0
- simtools/schemas/model_parameters/camera_filter_incidence_angle.schema.yml +29 -0
- simtools/schemas/model_parameters/camera_pixels.schema.yml +36 -0
- simtools/schemas/model_parameters/camera_transmission.schema.yml +41 -0
- simtools/schemas/model_parameters/channels_per_chip.schema.yml +36 -0
- simtools/schemas/model_parameters/correct_nsb_spectrum_to_telescope_altitude.schema.yml +35 -0
- simtools/schemas/model_parameters/corsika_cherenkov_photon_bunch_size.schema.yml +27 -0
- simtools/schemas/model_parameters/corsika_cherenkov_photon_wavelength_range.schema.yml +38 -0
- simtools/schemas/model_parameters/corsika_first_interaction_height.schema.yml +28 -0
- simtools/schemas/model_parameters/corsika_iact_io_buffer.schema.yml +23 -0
- simtools/schemas/model_parameters/corsika_iact_max_bunches.schema.yml +27 -0
- simtools/schemas/model_parameters/corsika_iact_split_auto.schema.yml +28 -0
- simtools/schemas/model_parameters/corsika_longitudinal_shower_development.schema.yml +27 -0
- simtools/schemas/model_parameters/corsika_observation_level.schema.yml +38 -0
- simtools/schemas/model_parameters/corsika_particle_kinetic_energy_cutoff.schema.yml +52 -0
- simtools/schemas/model_parameters/corsika_starting_grammage.schema.yml +27 -0
- simtools/schemas/model_parameters/dark_events.schema.yml +32 -0
- simtools/schemas/model_parameters/default_trigger.schema.yml +35 -0
- simtools/schemas/model_parameters/design_model.schema.yml +31 -0
- simtools/schemas/model_parameters/disc_ac_coupled.schema.yml +32 -0
- simtools/schemas/model_parameters/disc_bins.schema.yml +39 -0
- simtools/schemas/model_parameters/disc_start.schema.yml +41 -0
- simtools/schemas/model_parameters/discriminator_amplitude.schema.yml +42 -0
- simtools/schemas/model_parameters/discriminator_fall_time.schema.yml +41 -0
- simtools/schemas/model_parameters/discriminator_gate_length.schema.yml +41 -0
- simtools/schemas/model_parameters/discriminator_hysteresis.schema.yml +39 -0
- simtools/schemas/model_parameters/discriminator_output_amplitude.schema.yml +40 -0
- simtools/schemas/model_parameters/discriminator_output_var_percent.schema.yml +41 -0
- simtools/schemas/model_parameters/discriminator_pulse_shape.schema.yml +33 -0
- simtools/schemas/model_parameters/discriminator_rise_time.schema.yml +42 -0
- simtools/schemas/model_parameters/discriminator_scale_threshold.schema.yml +37 -0
- simtools/schemas/model_parameters/discriminator_sigsum_over_threshold.schema.yml +44 -0
- simtools/schemas/model_parameters/discriminator_threshold.schema.yml +36 -0
- simtools/schemas/model_parameters/discriminator_time_over_threshold.schema.yml +45 -0
- simtools/schemas/model_parameters/discriminator_var_gate_length.schema.yml +40 -0
- simtools/schemas/model_parameters/discriminator_var_sigsum_over_threshold.schema.yml +41 -0
- simtools/schemas/model_parameters/discriminator_var_threshold.schema.yml +38 -0
- simtools/schemas/model_parameters/discriminator_var_time_over_threshold.schema.yml +38 -0
- simtools/schemas/model_parameters/dish_shape_length.schema.yml +41 -0
- simtools/schemas/model_parameters/dsum_clipping.schema.yml +38 -0
- simtools/schemas/model_parameters/dsum_ignore_below.schema.yml +38 -0
- simtools/schemas/model_parameters/dsum_offset.schema.yml +37 -0
- simtools/schemas/model_parameters/dsum_pedsub.schema.yml +33 -0
- simtools/schemas/model_parameters/dsum_pre_clipping.schema.yml +39 -0
- simtools/schemas/model_parameters/dsum_prescale.schema.yml +44 -0
- simtools/schemas/model_parameters/dsum_presum_max.schema.yml +38 -0
- simtools/schemas/model_parameters/dsum_presum_shift.schema.yml +45 -0
- simtools/schemas/model_parameters/dsum_shaping.schema.yml +44 -0
- simtools/schemas/model_parameters/dsum_shaping_renormalize.schema.yml +32 -0
- simtools/schemas/model_parameters/dsum_threshold.schema.yml +43 -0
- simtools/schemas/model_parameters/dsum_zero_clip.schema.yml +42 -0
- simtools/schemas/model_parameters/effective_focal_length.schema.yml +61 -0
- simtools/schemas/model_parameters/epsg_code.schema.yml +37 -0
- simtools/schemas/model_parameters/fadc_ac_coupled.schema.yml +35 -0
- simtools/schemas/model_parameters/fadc_amplitude.schema.yml +46 -0
- simtools/schemas/model_parameters/fadc_bins.schema.yml +40 -0
- simtools/schemas/model_parameters/fadc_compensate_pedestal.schema.yml +50 -0
- simtools/schemas/model_parameters/fadc_dev_pedestal.schema.yml +38 -0
- simtools/schemas/model_parameters/fadc_err_compensate_pedestal.schema.yml +42 -0
- simtools/schemas/model_parameters/fadc_err_pedestal.schema.yml +49 -0
- simtools/schemas/model_parameters/fadc_lg_amplitude.schema.yml +47 -0
- simtools/schemas/model_parameters/fadc_lg_compensate_pedestal.schema.yml +51 -0
- simtools/schemas/model_parameters/fadc_lg_dev_pedestal.schema.yml +37 -0
- simtools/schemas/model_parameters/fadc_lg_err_compensate_pedestal.schema.yml +43 -0
- simtools/schemas/model_parameters/fadc_lg_err_pedestal.schema.yml +49 -0
- simtools/schemas/model_parameters/fadc_lg_max_signal.schema.yml +43 -0
- simtools/schemas/model_parameters/fadc_lg_max_sum.schema.yml +39 -0
- simtools/schemas/model_parameters/fadc_lg_noise.schema.yml +42 -0
- simtools/schemas/model_parameters/fadc_lg_pedestal.schema.yml +40 -0
- simtools/schemas/model_parameters/fadc_lg_sensitivity.schema.yml +50 -0
- simtools/schemas/model_parameters/fadc_lg_sysvar_pedestal.schema.yml +42 -0
- simtools/schemas/model_parameters/fadc_lg_var_pedestal.schema.yml +41 -0
- simtools/schemas/model_parameters/fadc_lg_var_sensitivity.schema.yml +42 -0
- simtools/schemas/model_parameters/fadc_max_signal.schema.yml +43 -0
- simtools/schemas/model_parameters/fadc_max_sum.schema.yml +39 -0
- simtools/schemas/model_parameters/fadc_mhz.schema.yml +31 -0
- simtools/schemas/model_parameters/fadc_noise.schema.yml +41 -0
- simtools/schemas/model_parameters/fadc_pedestal.schema.yml +40 -0
- simtools/schemas/model_parameters/fadc_pulse_shape.schema.yml +39 -0
- simtools/schemas/model_parameters/fadc_sensitivity.schema.yml +50 -0
- simtools/schemas/model_parameters/fadc_sum_bins.schema.yml +43 -0
- simtools/schemas/model_parameters/fadc_sum_offset.schema.yml +43 -0
- simtools/schemas/model_parameters/fadc_sysvar_pedestal.schema.yml +42 -0
- simtools/schemas/model_parameters/fadc_var_pedestal.schema.yml +41 -0
- simtools/schemas/model_parameters/fadc_var_sensitivity.schema.yml +42 -0
- simtools/schemas/model_parameters/flatfielding.schema.yml +37 -0
- simtools/schemas/model_parameters/focal_length.schema.yml +45 -0
- simtools/schemas/model_parameters/focal_surface_parameters.schema.yml +158 -0
- simtools/schemas/model_parameters/focal_surface_ref_radius.schema.yml +29 -0
- simtools/schemas/model_parameters/focus_offset.schema.yml +66 -0
- simtools/schemas/model_parameters/gain_variation.schema.yml +43 -0
- simtools/schemas/model_parameters/geomag_horizontal.schema.yml +34 -0
- simtools/schemas/model_parameters/geomag_rotation.schema.yml +37 -0
- simtools/schemas/model_parameters/geomag_vertical.schema.yml +34 -0
- simtools/schemas/model_parameters/hg_lg_variation.schema.yml +36 -0
- simtools/schemas/model_parameters/iobuf_maximum.schema.yml +34 -0
- simtools/schemas/model_parameters/iobuf_output_maximum.schema.yml +34 -0
- simtools/schemas/model_parameters/laser_events.schema.yml +36 -0
- simtools/schemas/model_parameters/laser_external_trigger.schema.yml +35 -0
- simtools/schemas/model_parameters/laser_photons.schema.yml +32 -0
- simtools/schemas/model_parameters/laser_pulse_exptime.schema.yml +34 -0
- simtools/schemas/model_parameters/laser_pulse_offset.schema.yml +34 -0
- simtools/schemas/model_parameters/laser_pulse_sigtime.schema.yml +33 -0
- simtools/schemas/model_parameters/laser_pulse_twidth.schema.yml +33 -0
- simtools/schemas/model_parameters/laser_var_photons.schema.yml +33 -0
- simtools/schemas/model_parameters/laser_wavelength.schema.yml +33 -0
- simtools/schemas/model_parameters/led_events.schema.yml +34 -0
- simtools/schemas/model_parameters/led_photons.schema.yml +34 -0
- simtools/schemas/model_parameters/led_pulse_offset.schema.yml +32 -0
- simtools/schemas/model_parameters/led_pulse_sigtime.schema.yml +33 -0
- simtools/schemas/model_parameters/led_var_photons.schema.yml +34 -0
- simtools/schemas/model_parameters/lightguide_efficiency_vs_incidence_angle.schema.yml +41 -0
- simtools/schemas/model_parameters/lightguide_efficiency_vs_wavelength.schema.yml +43 -0
- simtools/schemas/model_parameters/min_photoelectrons.schema.yml +35 -0
- simtools/schemas/model_parameters/min_photons.schema.yml +32 -0
- simtools/schemas/model_parameters/mirror_align_random_distance.schema.yml +36 -0
- simtools/schemas/model_parameters/mirror_align_random_horizontal.schema.yml +64 -0
- simtools/schemas/model_parameters/mirror_align_random_vertical.schema.yml +64 -0
- simtools/schemas/model_parameters/mirror_class.schema.yml +41 -0
- simtools/schemas/model_parameters/mirror_degraded_reflection.schema.yml +51 -0
- simtools/schemas/model_parameters/mirror_focal_length.schema.yml +42 -0
- simtools/schemas/model_parameters/mirror_list.schema.yml +38 -0
- simtools/schemas/model_parameters/mirror_offset.schema.yml +41 -0
- simtools/schemas/model_parameters/mirror_panel_2f_measurements.schema.yml +39 -0
- simtools/schemas/model_parameters/mirror_reflection_random_angle.schema.yml +61 -0
- simtools/schemas/model_parameters/mirror_reflectivity.schema.yml +40 -0
- simtools/schemas/model_parameters/multiplicity_offset.schema.yml +46 -0
- simtools/schemas/model_parameters/nsb_autoscale_airmass.schema.yml +51 -0
- simtools/schemas/model_parameters/nsb_gain_drop_scale.schema.yml +37 -0
- simtools/schemas/model_parameters/nsb_offaxis.schema.yml +79 -0
- simtools/schemas/model_parameters/nsb_pixel_rate.schema.yml +47 -0
- simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +34 -0
- simtools/schemas/model_parameters/nsb_reference_value.schema.yml +33 -0
- simtools/schemas/model_parameters/nsb_scaling_factor.schema.yml +35 -0
- simtools/schemas/model_parameters/nsb_skymap.schema.yml +39 -0
- simtools/schemas/model_parameters/nsb_spectrum.schema.yml +50 -0
- simtools/schemas/model_parameters/num_gains.schema.yml +34 -0
- simtools/schemas/model_parameters/only_triggered_telescopes.schema.yml +33 -0
- simtools/schemas/model_parameters/optics_properties.schema.yml +31 -0
- simtools/schemas/model_parameters/parabolic_dish.schema.yml +32 -0
- simtools/schemas/model_parameters/pedestal_events.schema.yml +32 -0
- simtools/schemas/model_parameters/photon_delay.schema.yml +38 -0
- simtools/schemas/model_parameters/photons_per_run.schema.yml +33 -0
- simtools/schemas/model_parameters/pixel_cells.schema.yml +35 -0
- simtools/schemas/model_parameters/pixels_parallel.schema.yml +54 -0
- simtools/schemas/model_parameters/pixeltrg_time_step.schema.yml +40 -0
- simtools/schemas/model_parameters/pm_average_gain.schema.yml +34 -0
- simtools/schemas/model_parameters/pm_collection_efficiency.schema.yml +40 -0
- simtools/schemas/model_parameters/pm_gain_index.schema.yml +36 -0
- simtools/schemas/model_parameters/pm_photoelectron_spectrum.schema.yml +41 -0
- simtools/schemas/model_parameters/pm_transit_time.schema.yml +63 -0
- simtools/schemas/model_parameters/pm_voltage_variation.schema.yml +39 -0
- simtools/schemas/model_parameters/primary_mirror_degraded_map.schema.yml +42 -0
- simtools/schemas/model_parameters/primary_mirror_diameter.schema.yml +33 -0
- simtools/schemas/model_parameters/primary_mirror_hole_diameter.schema.yml +33 -0
- simtools/schemas/model_parameters/primary_mirror_incidence_angle.schema.yml +29 -0
- simtools/schemas/model_parameters/primary_mirror_parameters.schema.yml +168 -0
- simtools/schemas/model_parameters/primary_mirror_ref_radius.schema.yml +36 -0
- simtools/schemas/model_parameters/primary_mirror_segmentation.schema.yml +34 -0
- simtools/schemas/model_parameters/qe_variation.schema.yml +43 -0
- simtools/schemas/model_parameters/quantum_efficiency.schema.yml +42 -0
- simtools/schemas/model_parameters/random_focal_length.schema.yml +45 -0
- simtools/schemas/model_parameters/random_generator.schema.yml +36 -0
- simtools/schemas/model_parameters/reference_point_altitude.schema.yml +35 -0
- simtools/schemas/model_parameters/reference_point_latitude.schema.yml +36 -0
- simtools/schemas/model_parameters/reference_point_longitude.schema.yml +36 -0
- simtools/schemas/model_parameters/reference_point_utm_east.schema.yml +34 -0
- simtools/schemas/model_parameters/reference_point_utm_north.schema.yml +34 -0
- simtools/schemas/model_parameters/sampled_output.schema.yml +31 -0
- simtools/schemas/model_parameters/save_pe_with_amplitude.schema.yml +34 -0
- simtools/schemas/model_parameters/secondary_mirror_baffle.schema.yml +79 -0
- simtools/schemas/model_parameters/secondary_mirror_degraded_map.schema.yml +42 -0
- simtools/schemas/model_parameters/secondary_mirror_degraded_reflection.schema.yml +41 -0
- simtools/schemas/model_parameters/secondary_mirror_diameter.schema.yml +33 -0
- simtools/schemas/model_parameters/secondary_mirror_hole_diameter.schema.yml +36 -0
- simtools/schemas/model_parameters/secondary_mirror_incidence_angle.schema.yml +29 -0
- simtools/schemas/model_parameters/secondary_mirror_parameters.schema.yml +168 -0
- simtools/schemas/model_parameters/secondary_mirror_ref_radius.schema.yml +36 -0
- simtools/schemas/model_parameters/secondary_mirror_reflectivity.schema.yml +35 -0
- simtools/schemas/model_parameters/secondary_mirror_segmentation.schema.yml +37 -0
- simtools/schemas/model_parameters/secondary_mirror_shadow_diameter.schema.yml +40 -0
- simtools/schemas/model_parameters/secondary_mirror_shadow_offset.schema.yml +40 -0
- simtools/schemas/model_parameters/store_photoelectrons.schema.yml +41 -0
- simtools/schemas/model_parameters/tailcut_scale.schema.yml +40 -0
- simtools/schemas/model_parameters/telescope_axis_height.schema.yml +31 -0
- simtools/schemas/model_parameters/telescope_random_angle.schema.yml +35 -0
- simtools/schemas/model_parameters/telescope_random_error.schema.yml +34 -0
- simtools/schemas/model_parameters/telescope_sphere_radius.schema.yml +37 -0
- simtools/schemas/model_parameters/telescope_transmission.schema.yml +113 -0
- simtools/schemas/model_parameters/teltrig_min_sigsum.schema.yml +41 -0
- simtools/schemas/model_parameters/teltrig_min_time.schema.yml +36 -0
- simtools/schemas/model_parameters/transit_time_calib_error.schema.yml +36 -0
- simtools/schemas/model_parameters/transit_time_compensate_error.schema.yml +37 -0
- simtools/schemas/model_parameters/transit_time_compensate_step.schema.yml +38 -0
- simtools/schemas/model_parameters/transit_time_error.schema.yml +45 -0
- simtools/schemas/model_parameters/transit_time_jitter.schema.yml +36 -0
- simtools/schemas/model_parameters/trigger_current_limit.schema.yml +32 -0
- simtools/schemas/model_parameters/trigger_delay_compensation.schema.yml +53 -0
- simtools/schemas/model_parameters/trigger_pixels.schema.yml +40 -0
- simtools/simtel/simtel_config_reader.py +353 -0
- simtools/simtel/simtel_config_writer.py +244 -63
- simtools/simtel/{simtel_events.py → simtel_io_events.py} +26 -25
- simtools/simtel/simtel_io_histogram.py +661 -0
- simtools/simtel/simtel_io_histograms.py +569 -0
- simtools/simtel/simulator_array.py +145 -0
- simtools/simtel/{simtel_runner_camera_efficiency.py → simulator_camera_efficiency.py} +76 -52
- simtools/simtel/simulator_light_emission.py +473 -0
- simtools/simtel/simulator_ray_tracing.py +262 -0
- simtools/simulator.py +220 -446
- simtools/testing/__init__.py +0 -0
- simtools/testing/assertions.py +151 -0
- simtools/testing/configuration.py +226 -0
- simtools/testing/helpers.py +42 -0
- simtools/testing/validate_output.py +240 -0
- simtools/utils/general.py +340 -437
- simtools/utils/geometry.py +12 -12
- simtools/utils/names.py +258 -644
- simtools/utils/value_conversion.py +176 -0
- simtools/version.py +2 -0
- simtools/visualization/legend_handlers.py +135 -152
- simtools/visualization/plot_camera.py +379 -0
- simtools/visualization/visualize.py +346 -167
- gammasimtools-0.6.1.dist-info/METADATA +0 -180
- gammasimtools-0.6.1.dist-info/RECORD +0 -91
- gammasimtools-0.6.1.dist-info/entry_points.txt +0 -23
- simtools/applications/db_development_tools/add_new_parameter_to_db.py +0 -81
- simtools/applications/db_development_tools/add_unit_to_parameter_in_db.py +0 -59
- simtools/applications/db_development_tools/mark_non_optics_parameters_non_applicable.py +0 -102
- simtools/applications/get_parameter.py +0 -92
- simtools/applications/make_regular_arrays.py +0 -160
- simtools/applications/produce_array_config.py +0 -136
- simtools/applications/production.py +0 -313
- simtools/applications/sim_showers_for_trigger_rates.py +0 -187
- simtools/applications/tune_psf.py +0 -334
- simtools/corsika/corsika_default_config.py +0 -282
- simtools/corsika/corsika_runner.py +0 -450
- simtools/corsika_simtel/corsika_simtel_runner.py +0 -197
- simtools/db_handler.py +0 -1480
- simtools/ray_tracing.py +0 -525
- simtools/simtel/simtel_histograms.py +0 -414
- simtools/simtel/simtel_runner.py +0 -244
- simtools/simtel/simtel_runner_array.py +0 -293
- simtools/simtel/simtel_runner_ray_tracing.py +0 -277
- {gammasimtools-0.6.1.dist-info → gammasimtools-0.8.1.dist-info}/LICENSE +0 -0
- {gammasimtools-0.6.1.dist-info → gammasimtools-0.8.1.dist-info}/top_level.txt +0 -0
- /simtools/{corsika_simtel → db}/__init__.py +0 -0
|
File without changes
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""Functions asserting certain conditions are met (used e.g., in integration tests)."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
from collections import defaultdict
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import yaml
|
|
10
|
+
|
|
11
|
+
_logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def assert_file_type(file_type, file_name):
|
|
15
|
+
"""
|
|
16
|
+
Assert that the file is of the given type.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
file_type: str
|
|
21
|
+
File type (json, yaml).
|
|
22
|
+
file_name: str
|
|
23
|
+
File name.
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
if file_type == "json":
|
|
27
|
+
try:
|
|
28
|
+
with open(file_name, encoding="utf-8") as file:
|
|
29
|
+
json.load(file)
|
|
30
|
+
return True
|
|
31
|
+
except (json.JSONDecodeError, FileNotFoundError):
|
|
32
|
+
return False
|
|
33
|
+
if file_type in ("yaml", "yml"):
|
|
34
|
+
if Path(file_name).suffix[1:] not in ("yaml", "yml"):
|
|
35
|
+
return False
|
|
36
|
+
try:
|
|
37
|
+
with open(file_name, encoding="utf-8") as file:
|
|
38
|
+
yaml.safe_load(file)
|
|
39
|
+
return True
|
|
40
|
+
except (yaml.YAMLError, FileNotFoundError):
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
# no dedicated tests for other file types, checking suffix only
|
|
44
|
+
_logger.info(f"File type test is checking suffix only for {file_name} (suffix: {file_type}))")
|
|
45
|
+
return Path(file_name).suffix[1:] == file_type
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def assert_n_showers_and_energy_range(file):
|
|
49
|
+
"""
|
|
50
|
+
Assert the number of showers and the energy range.
|
|
51
|
+
|
|
52
|
+
The number of showers should be consistent with the required one (up to 1% tolerance)
|
|
53
|
+
and the energies simulated are required to be within the configured ones.
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
file: Path
|
|
58
|
+
Path to the sim_telarray file.
|
|
59
|
+
|
|
60
|
+
"""
|
|
61
|
+
from eventio.simtel.simtelfile import SimTelFile # pylint: disable=import-outside-toplevel
|
|
62
|
+
|
|
63
|
+
simulated_energies = []
|
|
64
|
+
simulation_config = {}
|
|
65
|
+
with SimTelFile(file) as f:
|
|
66
|
+
simulation_config = f.mc_run_headers[0]
|
|
67
|
+
for event in f.iter_mc_events():
|
|
68
|
+
simulated_energies.append(event["mc_shower"]["energy"])
|
|
69
|
+
|
|
70
|
+
# The relative tolerance is set to 1% because ~0.5% shower simulations do not
|
|
71
|
+
# succeed, without resulting in an error. This tolerance therefore is not an issue.
|
|
72
|
+
consistent_n_showers = np.isclose(
|
|
73
|
+
len(np.unique(simulated_energies)), simulation_config["n_showers"], rtol=1e-2
|
|
74
|
+
)
|
|
75
|
+
consistent_energy_range = all(
|
|
76
|
+
simulation_config["E_range"][0] <= energy <= simulation_config["E_range"][1]
|
|
77
|
+
for energy in simulated_energies
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
return consistent_n_showers and consistent_energy_range
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def assert_expected_output(file, expected_output):
|
|
84
|
+
"""
|
|
85
|
+
Assert that the expected output is present in the sim_telarray file.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
file: Path
|
|
90
|
+
Path to the sim_telarray file.
|
|
91
|
+
expected_output: dict
|
|
92
|
+
Expected output values.
|
|
93
|
+
|
|
94
|
+
"""
|
|
95
|
+
from eventio.simtel.simtelfile import SimTelFile # pylint: disable=import-outside-toplevel
|
|
96
|
+
|
|
97
|
+
item_to_check = defaultdict(list)
|
|
98
|
+
with SimTelFile(file) as f:
|
|
99
|
+
for event in f:
|
|
100
|
+
if "pe_sum" in expected_output:
|
|
101
|
+
item_to_check["pe_sum"].extend(
|
|
102
|
+
event["photoelectron_sums"]["n_pe"][event["photoelectron_sums"]["n_pe"] > 0]
|
|
103
|
+
)
|
|
104
|
+
if "trigger_time" in expected_output:
|
|
105
|
+
item_to_check["trigger_time"].extend(event["trigger_information"]["trigger_times"])
|
|
106
|
+
if "photons" in expected_output:
|
|
107
|
+
item_to_check["photons"].extend(
|
|
108
|
+
event["photoelectron_sums"]["photons_atm_qe"][
|
|
109
|
+
event["photoelectron_sums"]["photons"] > 0
|
|
110
|
+
]
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
for key, value in expected_output.items():
|
|
114
|
+
if len(item_to_check[key]) == 0:
|
|
115
|
+
_logger.error(f"No data found for {key}")
|
|
116
|
+
return False
|
|
117
|
+
|
|
118
|
+
if not value[0] < np.mean(item_to_check[key]) < value[1]:
|
|
119
|
+
_logger.error(
|
|
120
|
+
f"Mean of {key} is not in the expected range, got {np.mean(item_to_check[key])}"
|
|
121
|
+
)
|
|
122
|
+
return False
|
|
123
|
+
|
|
124
|
+
return True
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def check_output_from_sim_telarray(file, expected_output):
|
|
128
|
+
"""
|
|
129
|
+
Check that the sim_telarray simulation result is reasonable and matches the expected output.
|
|
130
|
+
|
|
131
|
+
Parameters
|
|
132
|
+
----------
|
|
133
|
+
file: Path
|
|
134
|
+
Path to the sim_telarray file.
|
|
135
|
+
expected_output: dict
|
|
136
|
+
Expected output values.
|
|
137
|
+
|
|
138
|
+
Raises
|
|
139
|
+
------
|
|
140
|
+
ValueError
|
|
141
|
+
If the file is not a zstd compressed file.
|
|
142
|
+
"""
|
|
143
|
+
if file.suffix != ".zst":
|
|
144
|
+
raise ValueError(
|
|
145
|
+
f"Expected output file {file} is not a zstd compressed file "
|
|
146
|
+
f"(i.e., a sim_telarray file)."
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
return assert_n_showers_and_energy_range(file=file) and assert_expected_output(
|
|
150
|
+
file=file, expected_output=expected_output
|
|
151
|
+
)
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"""Integration test configuration."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
import yaml
|
|
8
|
+
|
|
9
|
+
import simtools.utils.general as gen
|
|
10
|
+
|
|
11
|
+
_logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_list_of_test_configurations(config_files):
|
|
15
|
+
"""
|
|
16
|
+
Return list of test configuration dictionaries or test names.
|
|
17
|
+
|
|
18
|
+
Read all configuration files for testing.
|
|
19
|
+
Add "--help" and "--version" calls for all applications.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
config_files: list
|
|
24
|
+
List of integration test configuration files.
|
|
25
|
+
|
|
26
|
+
Returns
|
|
27
|
+
-------
|
|
28
|
+
list:
|
|
29
|
+
list of test names or of configuration dictionaries.
|
|
30
|
+
|
|
31
|
+
"""
|
|
32
|
+
_logger.debug(f"Configuration files: {config_files}")
|
|
33
|
+
|
|
34
|
+
configs = _read_configs_from_files(config_files)
|
|
35
|
+
|
|
36
|
+
# list of all applications
|
|
37
|
+
# (needs to be sorted for pytest-xdist, see Known Limitations in their website)
|
|
38
|
+
_applications = sorted({item["APPLICATION"] for item in configs if "APPLICATION" in item})
|
|
39
|
+
for app in _applications:
|
|
40
|
+
configs.extend(
|
|
41
|
+
[
|
|
42
|
+
{"APPLICATION": app, "TEST_NAME": "auto-help", "CONFIGURATION": {"HELP": True}},
|
|
43
|
+
{
|
|
44
|
+
"APPLICATION": app,
|
|
45
|
+
"TEST_NAME": "auto-version",
|
|
46
|
+
"CONFIGURATION": {"VERSION": True},
|
|
47
|
+
},
|
|
48
|
+
{"APPLICATION": app, "TEST_NAME": "auto-no_config"},
|
|
49
|
+
]
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
configs,
|
|
54
|
+
[
|
|
55
|
+
f"{item.get('APPLICATION', 'no-app-name')}_{item.get('TEST_NAME', 'no-test-name')}"
|
|
56
|
+
for item in configs
|
|
57
|
+
],
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _read_configs_from_files(config_files):
|
|
62
|
+
"""Read test configuration from files."""
|
|
63
|
+
configs = []
|
|
64
|
+
for config_file in config_files:
|
|
65
|
+
# read config file
|
|
66
|
+
# remove new line characters from config - otherwise issues
|
|
67
|
+
# with especially long file names
|
|
68
|
+
_dict = gen.remove_substring_recursively_from_dict(
|
|
69
|
+
gen.collect_data_from_file(file_name=config_file), substring="\n"
|
|
70
|
+
)
|
|
71
|
+
configs.append(_dict.get("CTA_SIMPIPE", None))
|
|
72
|
+
return configs
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def configure(config, tmp_test_directory, request):
|
|
76
|
+
"""
|
|
77
|
+
Prepare configuration and command for integration tests.
|
|
78
|
+
|
|
79
|
+
Parameters
|
|
80
|
+
----------
|
|
81
|
+
config: dict
|
|
82
|
+
Configuration dictionary.
|
|
83
|
+
tmp_test_directory: str
|
|
84
|
+
Temporary test directory (from pytest fixture).
|
|
85
|
+
request: request
|
|
86
|
+
Request object.
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
-------
|
|
90
|
+
str: command to run the application test.
|
|
91
|
+
str: config file model version.
|
|
92
|
+
|
|
93
|
+
"""
|
|
94
|
+
tmp_output_path = create_tmp_output_path(tmp_test_directory, config)
|
|
95
|
+
model_version_requested = request.config.getoption("--model_version")
|
|
96
|
+
|
|
97
|
+
if "CONFIGURATION" in config:
|
|
98
|
+
_skip_test_for_model_version(config, model_version_requested)
|
|
99
|
+
|
|
100
|
+
config_file, config_string, config_file_model_version = _prepare_test_options(
|
|
101
|
+
config["CONFIGURATION"],
|
|
102
|
+
output_path=tmp_output_path,
|
|
103
|
+
model_version=model_version_requested,
|
|
104
|
+
)
|
|
105
|
+
else:
|
|
106
|
+
config_file = None
|
|
107
|
+
config_string = None
|
|
108
|
+
config_file_model_version = None
|
|
109
|
+
|
|
110
|
+
cmd = get_application_command(
|
|
111
|
+
app=config.get("APPLICATION", None),
|
|
112
|
+
config_file=config_file,
|
|
113
|
+
config_string=config_string,
|
|
114
|
+
)
|
|
115
|
+
return cmd, config_file_model_version
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _skip_test_for_model_version(config, model_version_requested):
|
|
119
|
+
"""Skip test if model version requested is not supported."""
|
|
120
|
+
if config.get("MODEL_VERSION_USE_CURRENT") is None or model_version_requested is None:
|
|
121
|
+
return
|
|
122
|
+
model_version_config = config["CONFIGURATION"]["MODEL_VERSION"]
|
|
123
|
+
if model_version_requested != model_version_config:
|
|
124
|
+
pytest.skip(
|
|
125
|
+
f"Model version requested {model_version_requested} not supported for this test"
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _prepare_test_options(config, output_path, model_version=None):
|
|
130
|
+
"""
|
|
131
|
+
Prepare test configuration.
|
|
132
|
+
|
|
133
|
+
This means either to write a temporary config file
|
|
134
|
+
or to return a single string for single boolean options (e.g., --version).
|
|
135
|
+
Change output path and file to paths provided with output_path.
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
config: dict
|
|
140
|
+
Dictionary with the configuration for the application test.
|
|
141
|
+
output_path: str
|
|
142
|
+
Output path.
|
|
143
|
+
model_version: str
|
|
144
|
+
Model versions (default: use those given in config files)
|
|
145
|
+
|
|
146
|
+
Returns
|
|
147
|
+
-------
|
|
148
|
+
config_file: str
|
|
149
|
+
Path to the temporary configuration file.
|
|
150
|
+
config_string: str
|
|
151
|
+
Command line configuration as single string.
|
|
152
|
+
config_file_model_version: str
|
|
153
|
+
Configuration file model version
|
|
154
|
+
|
|
155
|
+
"""
|
|
156
|
+
if len(config) == 1 and next(iter(config.values())) is True:
|
|
157
|
+
return None, "--" + next(iter(config.keys())).lower(), None
|
|
158
|
+
|
|
159
|
+
tmp_config_file = output_path / "tmp_config.yml"
|
|
160
|
+
config_file_model_version = config.get("MODEL_VERSION")
|
|
161
|
+
if model_version is not None and "MODEL_VERSION" in config:
|
|
162
|
+
config.update({"MODEL_VERSION": model_version})
|
|
163
|
+
if "OUTPUT_PATH" in config:
|
|
164
|
+
config.update({"OUTPUT_PATH": str(Path(output_path).joinpath(config["OUTPUT_PATH"]))})
|
|
165
|
+
config.update({"USE_PLAIN_OUTPUT_PATH": True})
|
|
166
|
+
if "DATA_DIRECTORY" in config:
|
|
167
|
+
config.update({"DATA_DIRECTORY": str(Path(output_path).joinpath(config["DATA_DIRECTORY"]))})
|
|
168
|
+
|
|
169
|
+
_logger.info(f"Writing config file: {tmp_config_file}")
|
|
170
|
+
with open(tmp_config_file, "w", encoding="utf-8") as file:
|
|
171
|
+
yaml.safe_dump(config, file, sort_keys=False)
|
|
172
|
+
|
|
173
|
+
return tmp_config_file, None, config_file_model_version
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def get_application_command(app, config_file=None, config_string=None):
|
|
177
|
+
"""
|
|
178
|
+
Return the command to run the application with the given config file.
|
|
179
|
+
|
|
180
|
+
Parameters
|
|
181
|
+
----------
|
|
182
|
+
app: str
|
|
183
|
+
Name of the application.
|
|
184
|
+
config_file: str
|
|
185
|
+
Configuration file.
|
|
186
|
+
config_string: str
|
|
187
|
+
Configuration string (e.g., '--version')
|
|
188
|
+
|
|
189
|
+
Returns
|
|
190
|
+
-------
|
|
191
|
+
str: command to run the application test.
|
|
192
|
+
|
|
193
|
+
"""
|
|
194
|
+
cmd = app if "simtools-" in app else f"python simtools/applications/{app}.py"
|
|
195
|
+
if config_string:
|
|
196
|
+
return f"{cmd} {config_string}"
|
|
197
|
+
if config_file is not None:
|
|
198
|
+
return f"{cmd} --config {config_file}"
|
|
199
|
+
return cmd
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def create_tmp_output_path(tmp_test_directory, config):
|
|
203
|
+
"""
|
|
204
|
+
Create temporary output path.
|
|
205
|
+
|
|
206
|
+
Parameters
|
|
207
|
+
----------
|
|
208
|
+
tmp_test_directory: str
|
|
209
|
+
Temporary directory.
|
|
210
|
+
config: dict
|
|
211
|
+
Configuration dictionary.
|
|
212
|
+
|
|
213
|
+
Returns
|
|
214
|
+
-------
|
|
215
|
+
str: path to the temporary output directory.
|
|
216
|
+
|
|
217
|
+
"""
|
|
218
|
+
try:
|
|
219
|
+
tmp_output_path = Path(tmp_test_directory).joinpath(
|
|
220
|
+
config["APPLICATION"] + "-" + config["TEST_NAME"]
|
|
221
|
+
)
|
|
222
|
+
except KeyError as exc:
|
|
223
|
+
raise KeyError(f"No application defined in configuration {config}.") from exc
|
|
224
|
+
tmp_output_path.mkdir(parents=True, exist_ok=True)
|
|
225
|
+
_logger.info(f"Temporary output path: {tmp_output_path}")
|
|
226
|
+
return tmp_output_path
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Helper functions for integration testing."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def skip_camera_efficiency(config):
|
|
9
|
+
"""Skip camera efficiency tests if the old version of testeff is used."""
|
|
10
|
+
if "camera-efficiency" in config["APPLICATION"]:
|
|
11
|
+
if not _new_testeff_version():
|
|
12
|
+
pytest.skip(
|
|
13
|
+
"Any applications calling the old version of testeff are skipped "
|
|
14
|
+
"due to a limitation of the old testeff not allowing to specify "
|
|
15
|
+
"the include directory. Please update your sim_telarray tarball."
|
|
16
|
+
)
|
|
17
|
+
full_test_name = f"{config['APPLICATION']}_{config['TEST_NAME']}"
|
|
18
|
+
if "simtools-validate-camera-efficiency_SSTS" == full_test_name:
|
|
19
|
+
pytest.skip(
|
|
20
|
+
"The test simtools-validate-camera-efficiency_SSTS is skipped "
|
|
21
|
+
"since the fake SST mirrors are not yet implemented (#1155)"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _new_testeff_version():
|
|
26
|
+
"""
|
|
27
|
+
Testeff has been updated to allow to specify the include directory.
|
|
28
|
+
|
|
29
|
+
This test checks if the new version is used.
|
|
30
|
+
"""
|
|
31
|
+
testeff_path = os.path.join(os.getenv("SIMTOOLS_SIMTEL_PATH"), "sim_telarray/testeff.c")
|
|
32
|
+
try:
|
|
33
|
+
with open(testeff_path, encoding="utf-8") as file:
|
|
34
|
+
file_content = file.read()
|
|
35
|
+
if (
|
|
36
|
+
"/* Combine the include paths such that those from '-I...' options */"
|
|
37
|
+
in file_content
|
|
38
|
+
):
|
|
39
|
+
return True
|
|
40
|
+
return False
|
|
41
|
+
except FileNotFoundError as exc:
|
|
42
|
+
raise FileNotFoundError("The testeff executable could not be found.") from exc
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""Compare application output to reference output."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
from astropy.table import Table
|
|
8
|
+
|
|
9
|
+
import simtools.utils.general as gen
|
|
10
|
+
from simtools.testing import assertions
|
|
11
|
+
|
|
12
|
+
_logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def validate_all_tests(config, request, config_file_model_version):
|
|
16
|
+
"""
|
|
17
|
+
Validate test output for all integration tests.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
config: dict
|
|
22
|
+
Integration test configuration dictionary.
|
|
23
|
+
request: request
|
|
24
|
+
Request object.
|
|
25
|
+
config_file_model_version: str
|
|
26
|
+
Model version from the configuration file.
|
|
27
|
+
|
|
28
|
+
"""
|
|
29
|
+
if request.config.getoption("--model_version") is None:
|
|
30
|
+
validate_application_output(config)
|
|
31
|
+
elif config_file_model_version is not None:
|
|
32
|
+
_from_command_line = request.config.getoption("--model_version")
|
|
33
|
+
_from_config_file = config_file_model_version
|
|
34
|
+
if _from_command_line == _from_config_file:
|
|
35
|
+
validate_application_output(config)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def validate_application_output(config):
|
|
39
|
+
"""
|
|
40
|
+
Validate application output against expected output.
|
|
41
|
+
|
|
42
|
+
Expected output is defined in configuration file.
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
config: dict
|
|
47
|
+
dictionary with the configuration for the application test.
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
if "INTEGRATION_TESTS" not in config:
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
for integration_test in config["INTEGRATION_TESTS"]:
|
|
54
|
+
_logger.info(f"Testing application output: {integration_test}")
|
|
55
|
+
if "REFERENCE_OUTPUT_FILE" in integration_test:
|
|
56
|
+
_validate_reference_output_file(config, integration_test)
|
|
57
|
+
|
|
58
|
+
if "OUTPUT_FILE" in integration_test:
|
|
59
|
+
_validate_output_path_and_file(config, integration_test)
|
|
60
|
+
|
|
61
|
+
if "FILE_TYPE" in integration_test:
|
|
62
|
+
assert assertions.assert_file_type(
|
|
63
|
+
integration_test["FILE_TYPE"],
|
|
64
|
+
Path(config["CONFIGURATION"]["OUTPUT_PATH"]).joinpath(
|
|
65
|
+
config["CONFIGURATION"]["OUTPUT_FILE"]
|
|
66
|
+
),
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _validate_reference_output_file(config, integration_test):
|
|
71
|
+
"""Compare with reference output file."""
|
|
72
|
+
assert compare_files(
|
|
73
|
+
integration_test["REFERENCE_OUTPUT_FILE"],
|
|
74
|
+
Path(config["CONFIGURATION"]["OUTPUT_PATH"]).joinpath(
|
|
75
|
+
config["CONFIGURATION"]["OUTPUT_FILE"]
|
|
76
|
+
),
|
|
77
|
+
integration_test.get("TOLERANCE", 1.0e-5),
|
|
78
|
+
integration_test.get("TEST_COLUMNS", None),
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _validate_output_path_and_file(config, integration_test):
|
|
83
|
+
"""Check if output path and file exist."""
|
|
84
|
+
_logger.info(f"PATH {config['CONFIGURATION']['OUTPUT_PATH']}")
|
|
85
|
+
_logger.info(f"File {integration_test['OUTPUT_FILE']}")
|
|
86
|
+
|
|
87
|
+
data_path = config["CONFIGURATION"].get(
|
|
88
|
+
"DATA_DIRECTORY", config["CONFIGURATION"]["OUTPUT_PATH"]
|
|
89
|
+
)
|
|
90
|
+
output_file_path = Path(data_path) / integration_test["OUTPUT_FILE"]
|
|
91
|
+
|
|
92
|
+
_logger.info(f"Checking path: {output_file_path}")
|
|
93
|
+
assert output_file_path.exists()
|
|
94
|
+
|
|
95
|
+
expected_output = [
|
|
96
|
+
d["EXPECTED_OUTPUT"] for d in config["INTEGRATION_TESTS"] if "EXPECTED_OUTPUT" in d
|
|
97
|
+
]
|
|
98
|
+
if expected_output and "log_hist" not in integration_test["OUTPUT_FILE"]:
|
|
99
|
+
# Get the expected output from the configuration file
|
|
100
|
+
expected_output = expected_output[0]
|
|
101
|
+
_logger.info(
|
|
102
|
+
f"Checking the output of {integration_test['OUTPUT_FILE']} "
|
|
103
|
+
"complies with the expected output: "
|
|
104
|
+
f"{expected_output}"
|
|
105
|
+
)
|
|
106
|
+
assert assertions.check_output_from_sim_telarray(output_file_path, expected_output)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def compare_files(file1, file2, tolerance=1.0e-5, test_columns=None):
|
|
110
|
+
"""
|
|
111
|
+
Compare two files of file type ecsv, json or yaml.
|
|
112
|
+
|
|
113
|
+
Parameters
|
|
114
|
+
----------
|
|
115
|
+
file1: str
|
|
116
|
+
First file to compare
|
|
117
|
+
file2: str
|
|
118
|
+
Second file to compare
|
|
119
|
+
tolerance: float
|
|
120
|
+
Tolerance for comparing numerical values.
|
|
121
|
+
test_columns: list
|
|
122
|
+
List of columns to compare. If None, all columns are compared.
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
bool
|
|
127
|
+
True if the files are equal, False otherwise.
|
|
128
|
+
|
|
129
|
+
"""
|
|
130
|
+
_file1_suffix = Path(file1).suffix
|
|
131
|
+
_file2_suffix = Path(file2).suffix
|
|
132
|
+
if _file1_suffix != _file2_suffix:
|
|
133
|
+
raise ValueError(f"File suffixes do not match: {file1} and {file2}")
|
|
134
|
+
if _file1_suffix == ".ecsv":
|
|
135
|
+
return compare_ecsv_files(file1, file2, tolerance, test_columns)
|
|
136
|
+
if _file1_suffix in (".json", ".yaml", ".yml"):
|
|
137
|
+
return compare_json_or_yaml_files(file1, file2)
|
|
138
|
+
|
|
139
|
+
_logger.warning(f"Unknown file type for files: {file1} and {file2}")
|
|
140
|
+
return False
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def compare_json_or_yaml_files(file1, file2, tolerance=1.0e-2):
|
|
144
|
+
"""
|
|
145
|
+
Compare two json or yaml files.
|
|
146
|
+
|
|
147
|
+
Take into account float comparison for sim_telarray string-embedded floats.
|
|
148
|
+
|
|
149
|
+
Parameters
|
|
150
|
+
----------
|
|
151
|
+
file1: str
|
|
152
|
+
First file to compare
|
|
153
|
+
file2: str
|
|
154
|
+
Second file to compare
|
|
155
|
+
tolerance: float
|
|
156
|
+
Tolerance for comparing numerical values.
|
|
157
|
+
|
|
158
|
+
Returns
|
|
159
|
+
-------
|
|
160
|
+
bool
|
|
161
|
+
True if the files are equal, False otherwise.
|
|
162
|
+
|
|
163
|
+
"""
|
|
164
|
+
data1 = gen.collect_data_from_file(file1)
|
|
165
|
+
data2 = gen.collect_data_from_file(file2)
|
|
166
|
+
|
|
167
|
+
_logger.debug(f"Comparing json/yaml files: {file1} and {file2}")
|
|
168
|
+
|
|
169
|
+
if data1 == data2:
|
|
170
|
+
return True
|
|
171
|
+
|
|
172
|
+
if "value" in data1 and isinstance(data1["value"], str):
|
|
173
|
+
value_list_1 = gen.convert_string_to_list(data1.pop("value"))
|
|
174
|
+
value_list_2 = gen.convert_string_to_list(data2.pop("value"))
|
|
175
|
+
return np.allclose(value_list_1, value_list_2, rtol=tolerance)
|
|
176
|
+
return data1 == data2
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def compare_ecsv_files(file1, file2, tolerance=1.0e-5, test_columns=None):
|
|
180
|
+
"""
|
|
181
|
+
Compare two ecsv files.
|
|
182
|
+
|
|
183
|
+
The comparison is successful if:
|
|
184
|
+
|
|
185
|
+
- same number of rows
|
|
186
|
+
- numerical values in columns are close
|
|
187
|
+
|
|
188
|
+
The comparison can be restricted to a subset of columns with some additional
|
|
189
|
+
cuts applied. This is configured through the test_columns parameter. This is
|
|
190
|
+
a list of dictionaries, where each dictionary contains the following
|
|
191
|
+
key-value pairs:
|
|
192
|
+
- TEST_COLUMN_NAME: column name to compare.
|
|
193
|
+
- CUT_COLUMN_NAME: column for filtering.
|
|
194
|
+
- CUT_CONDITION: condition for filtering.
|
|
195
|
+
|
|
196
|
+
Parameters
|
|
197
|
+
----------
|
|
198
|
+
file1: str
|
|
199
|
+
First file to compare
|
|
200
|
+
file2: str
|
|
201
|
+
Second file to compare
|
|
202
|
+
tolerance: float
|
|
203
|
+
Tolerance for comparing numerical values.
|
|
204
|
+
test_columns: list
|
|
205
|
+
List of columns to compare. If None, all columns are compared.
|
|
206
|
+
|
|
207
|
+
"""
|
|
208
|
+
_logger.info(f"Comparing files: {file1} and {file2}")
|
|
209
|
+
table1 = Table.read(file1, format="ascii.ecsv")
|
|
210
|
+
table2 = Table.read(file2, format="ascii.ecsv")
|
|
211
|
+
|
|
212
|
+
if test_columns is None:
|
|
213
|
+
test_columns = [{"TEST_COLUMN_NAME": col} for col in table1.colnames]
|
|
214
|
+
|
|
215
|
+
def generate_mask(table, column, condition):
|
|
216
|
+
"""Generate a boolean mask based on the condition (note the usage of eval)."""
|
|
217
|
+
return (
|
|
218
|
+
eval(f"table['{column}'] {condition}") # pylint: disable=eval-used
|
|
219
|
+
if condition
|
|
220
|
+
else np.ones(len(table), dtype=bool)
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
for col_dict in test_columns:
|
|
224
|
+
col_name = col_dict["TEST_COLUMN_NAME"]
|
|
225
|
+
mask1 = generate_mask(
|
|
226
|
+
table1, col_dict.get("CUT_COLUMN_NAME", ""), col_dict.get("CUT_CONDITION", "")
|
|
227
|
+
)
|
|
228
|
+
mask2 = generate_mask(
|
|
229
|
+
table2, col_dict.get("CUT_COLUMN_NAME", ""), col_dict.get("CUT_CONDITION", "")
|
|
230
|
+
)
|
|
231
|
+
table1_masked, table2_masked = table1[mask1], table2[mask2]
|
|
232
|
+
|
|
233
|
+
if len(table1_masked) != len(table2_masked):
|
|
234
|
+
return False
|
|
235
|
+
|
|
236
|
+
if np.issubdtype(table1_masked[col_name].dtype, np.floating):
|
|
237
|
+
if not np.allclose(table1_masked[col_name], table2_masked[col_name], rtol=tolerance):
|
|
238
|
+
return False
|
|
239
|
+
|
|
240
|
+
return True
|