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
simtools/model/camera.py
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
|
+
"""Definition and modeling of camera."""
|
|
2
|
+
|
|
1
3
|
import logging
|
|
2
4
|
|
|
3
5
|
import astropy.units as u
|
|
4
|
-
import matplotlib as mlp
|
|
5
|
-
import matplotlib.colors as mcolors
|
|
6
|
-
import matplotlib.patches as mpatches
|
|
7
|
-
import matplotlib.pyplot as plt
|
|
8
6
|
import numpy as np
|
|
9
|
-
from matplotlib.collections import PatchCollection
|
|
10
7
|
from scipy.spatial import cKDTree as KDTree
|
|
11
8
|
from scipy.spatial import distance
|
|
12
9
|
|
|
13
|
-
import simtools.visualization.legend_handlers as leg_h
|
|
14
|
-
from simtools.model.model_utils import is_two_mirror_telescope
|
|
15
|
-
from simtools.utils import names
|
|
16
10
|
from simtools.utils.geometry import rotate
|
|
17
11
|
|
|
18
12
|
__all__ = ["Camera"]
|
|
@@ -20,13 +14,14 @@ __all__ = ["Camera"]
|
|
|
20
14
|
|
|
21
15
|
class Camera:
|
|
22
16
|
"""
|
|
23
|
-
Camera class, defining pixel layout
|
|
24
|
-
|
|
17
|
+
Camera class, defining pixel layout.
|
|
18
|
+
|
|
19
|
+
This includes rotation, finding neighbor pixels, calculating FoV and plotting the camera.
|
|
25
20
|
|
|
26
21
|
Parameters
|
|
27
22
|
----------
|
|
28
23
|
telescope_model_name: string
|
|
29
|
-
As provided by the telescope model method TelescopeModel (
|
|
24
|
+
As provided by the telescope model method TelescopeModel (e.g., LSTN-01)
|
|
30
25
|
camera_config_file: string
|
|
31
26
|
The sim_telarray file name.
|
|
32
27
|
focal_length: float
|
|
@@ -34,31 +29,30 @@ class Camera:
|
|
|
34
29
|
in the same unit as the pixel positions in the camera_config_file, usually cm.
|
|
35
30
|
"""
|
|
36
31
|
|
|
37
|
-
# Constants for finding
|
|
32
|
+
# Constants for finding neighbor pixels.
|
|
38
33
|
PMT_NEIGHBOR_RADIUS_FACTOR = 1.1
|
|
39
34
|
SIPM_NEIGHBOR_RADIUS_FACTOR = 1.4
|
|
40
35
|
SIPM_ROW_COLUMN_DIST_FACTOR = 0.2
|
|
41
36
|
|
|
42
37
|
def __init__(self, telescope_model_name, camera_config_file, focal_length):
|
|
43
38
|
"""
|
|
44
|
-
Initialize Camera class, defining pixel layout
|
|
45
|
-
calculating FoV and plotting the camera.
|
|
46
|
-
"""
|
|
39
|
+
Initialize Camera class, defining pixel layout.
|
|
47
40
|
|
|
41
|
+
This includes rotation, finding neighbor pixels, calculating FoV and plotting the camera.
|
|
42
|
+
"""
|
|
48
43
|
self._logger = logging.getLogger(__name__)
|
|
49
44
|
|
|
50
|
-
self.
|
|
51
|
-
_, self._camera_name, _ = names.split_telescope_model_name(telescope_model_name)
|
|
45
|
+
self.telescope_model_name = telescope_model_name
|
|
52
46
|
self._camera_config_file = camera_config_file
|
|
53
|
-
self.
|
|
54
|
-
if self.
|
|
47
|
+
self.focal_length = focal_length
|
|
48
|
+
if self.focal_length <= 0:
|
|
55
49
|
raise ValueError("The focal length must be larger than zero")
|
|
56
|
-
self.
|
|
50
|
+
self.pixels = self.read_pixel_list(camera_config_file)
|
|
57
51
|
|
|
58
|
-
self.
|
|
52
|
+
self.pixels = self._rotate_pixels(self.pixels)
|
|
59
53
|
|
|
60
|
-
# Initialize an empty list of
|
|
61
|
-
self.
|
|
54
|
+
# Initialize an empty list of neighbors, to be calculated only when necessary.
|
|
55
|
+
self._neighbors = None
|
|
62
56
|
|
|
63
57
|
# Initialize an empty list of edge pixels, to be calculated only when necessary.
|
|
64
58
|
self._edge_pixel_indices = None
|
|
@@ -85,58 +79,105 @@ class Camera:
|
|
|
85
79
|
The hexagonal shapes differ in their orientation, where those denoted as 3 are rotated
|
|
86
80
|
clockwise by 30 degrees with respect to those denoted as 1.
|
|
87
81
|
"""
|
|
82
|
+
pixels = Camera.initialize_pixel_dict()
|
|
88
83
|
|
|
89
|
-
|
|
90
|
-
pixels["pixel_diameter"] = 9999
|
|
91
|
-
pixels["pixel_shape"] = 9999
|
|
92
|
-
pixels["pixel_spacing"] = 9999
|
|
93
|
-
pixels["lightguide_efficiency_angle_file"] = "none"
|
|
94
|
-
pixels["lightguide_efficiency_wavelength_file"] = "none"
|
|
95
|
-
pixels["rotate_angle"] = 0
|
|
96
|
-
pixels["x"] = []
|
|
97
|
-
pixels["y"] = []
|
|
98
|
-
pixels["pix_id"] = []
|
|
99
|
-
pixels["pix_on"] = []
|
|
100
|
-
|
|
101
|
-
with open(camera_config_file, "r", encoding="utf-8") as dat_file:
|
|
84
|
+
with open(camera_config_file, encoding="utf-8") as dat_file:
|
|
102
85
|
for line in dat_file:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
86
|
+
Camera.process_line(line, pixels)
|
|
87
|
+
|
|
88
|
+
Camera.validate_pixels(pixels, camera_config_file)
|
|
89
|
+
|
|
90
|
+
return pixels
|
|
91
|
+
|
|
92
|
+
@staticmethod
|
|
93
|
+
def initialize_pixel_dict():
|
|
94
|
+
"""
|
|
95
|
+
Initialize the pixel dictionary with default values.
|
|
96
|
+
|
|
97
|
+
Returns
|
|
98
|
+
-------
|
|
99
|
+
dict
|
|
100
|
+
A dictionary with default pixel properties.
|
|
101
|
+
"""
|
|
102
|
+
return {
|
|
103
|
+
"pixel_diameter": 9999,
|
|
104
|
+
"pixel_shape": 9999,
|
|
105
|
+
"pixel_spacing": 9999,
|
|
106
|
+
"lightguide_efficiency_angle_file": "none",
|
|
107
|
+
"lightguide_efficiency_wavelength_file": "none",
|
|
108
|
+
"rotate_angle": 0,
|
|
109
|
+
"x": [],
|
|
110
|
+
"y": [],
|
|
111
|
+
"pix_id": [],
|
|
112
|
+
"pix_on": [],
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@staticmethod
|
|
116
|
+
def process_line(line, pixels):
|
|
117
|
+
"""
|
|
118
|
+
Process a line from the camera config file and update the pixel dictionary.
|
|
119
|
+
|
|
120
|
+
Parameters
|
|
121
|
+
----------
|
|
122
|
+
line: string
|
|
123
|
+
A line from the camera config file.
|
|
124
|
+
pixels: dict
|
|
125
|
+
The pixel dictionary to update.
|
|
126
|
+
"""
|
|
127
|
+
pix_info = line.split()
|
|
128
|
+
|
|
129
|
+
if line.startswith("PixType"):
|
|
130
|
+
pixels["pixel_shape"] = int(pix_info[5].strip())
|
|
131
|
+
pixels["pixel_diameter"] = float(pix_info[6].strip())
|
|
132
|
+
pixels["lightguide_efficiency_angle_file"] = pix_info[8].strip().replace('"', "")
|
|
133
|
+
|
|
134
|
+
if len(pix_info) > 9:
|
|
135
|
+
pixels["lightguide_efficiency_wavelength_file"] = (
|
|
136
|
+
pix_info[9].strip().replace('"', "")
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
elif line.startswith("Rotate"):
|
|
140
|
+
pixels["rotate_angle"] = np.deg2rad(float(pix_info[1].strip()))
|
|
141
|
+
|
|
142
|
+
elif line.startswith("Pixel"):
|
|
143
|
+
pixels["x"].append(float(pix_info[3].strip()))
|
|
144
|
+
pixels["y"].append(float(pix_info[4].strip()))
|
|
145
|
+
pixels["pix_id"].append(int(pix_info[1].strip()))
|
|
146
|
+
|
|
147
|
+
if len(pix_info) > 9:
|
|
148
|
+
pixels["pix_on"].append(int(pix_info[9].strip()) != 0)
|
|
149
|
+
else:
|
|
150
|
+
pixels["pix_on"].append(True)
|
|
151
|
+
|
|
152
|
+
@staticmethod
|
|
153
|
+
def validate_pixels(pixels, camera_config_file):
|
|
154
|
+
"""
|
|
155
|
+
Validate the pixel dictionary to ensure it has correct values.
|
|
127
156
|
|
|
157
|
+
Parameters
|
|
158
|
+
----------
|
|
159
|
+
pixels: dict
|
|
160
|
+
The pixel dictionary to validate.
|
|
161
|
+
camera_config_file: string
|
|
162
|
+
The sim_telarray file name for error messages.
|
|
163
|
+
|
|
164
|
+
Raises
|
|
165
|
+
------
|
|
166
|
+
ValueError
|
|
167
|
+
If the pixel diameter or pixel shape is invalid.
|
|
168
|
+
"""
|
|
128
169
|
if pixels["pixel_diameter"] == 9999:
|
|
129
170
|
raise ValueError(f"Could not read the pixel diameter from {camera_config_file} file")
|
|
171
|
+
|
|
130
172
|
if pixels["pixel_shape"] not in [1, 2, 3]:
|
|
131
173
|
raise ValueError(
|
|
132
174
|
f"Pixel shape in {camera_config_file} unrecognized (has to be 1, 2 or 3)"
|
|
133
175
|
)
|
|
134
176
|
|
|
135
|
-
return pixels
|
|
136
|
-
|
|
137
177
|
def _rotate_pixels(self, pixels):
|
|
138
178
|
"""
|
|
139
179
|
Rotate the pixels according to the rotation angle given in pixels['rotate_angle'].
|
|
180
|
+
|
|
140
181
|
Additional rotation is added to get to the camera view of an observer facing the camera.
|
|
141
182
|
The angle for the axes rotation depends on the coordinate system in which the original
|
|
142
183
|
data was provided.
|
|
@@ -153,7 +194,6 @@ class Camera:
|
|
|
153
194
|
The pixels orientation for plotting is added to the dictionary in pixels['orientation'].
|
|
154
195
|
The orientation is determined by the pixel shape (see read_pixel_list for details).
|
|
155
196
|
"""
|
|
156
|
-
|
|
157
197
|
rotate_angle = pixels["rotate_angle"] * u.rad # So not to change the original angle
|
|
158
198
|
# The original pixel list is given such that
|
|
159
199
|
# x -> North, y -> West, z -> Up in the ground system.
|
|
@@ -188,8 +228,7 @@ class Camera:
|
|
|
188
228
|
int
|
|
189
229
|
number of pixels.
|
|
190
230
|
"""
|
|
191
|
-
|
|
192
|
-
return len(self._pixels["x"])
|
|
231
|
+
return len(self.pixels["x"])
|
|
193
232
|
|
|
194
233
|
def get_pixel_diameter(self):
|
|
195
234
|
"""
|
|
@@ -200,8 +239,7 @@ class Camera:
|
|
|
200
239
|
float
|
|
201
240
|
Pixel diameter (usually in cm).
|
|
202
241
|
"""
|
|
203
|
-
|
|
204
|
-
return self._pixels["pixel_diameter"]
|
|
242
|
+
return self.pixels["pixel_diameter"]
|
|
205
243
|
|
|
206
244
|
def get_pixel_active_solid_angle(self):
|
|
207
245
|
"""
|
|
@@ -212,16 +250,17 @@ class Camera:
|
|
|
212
250
|
float
|
|
213
251
|
active solid angle of a pixel in sr.
|
|
214
252
|
"""
|
|
215
|
-
|
|
216
253
|
pixel_area = self.get_pixel_diameter() ** 2
|
|
217
254
|
# In case we have hexagonal pixels:
|
|
218
255
|
if self.get_pixel_shape() == 1 or self.get_pixel_shape() == 3:
|
|
219
256
|
pixel_area *= np.sqrt(3) / 2
|
|
220
|
-
return pixel_area / (self.
|
|
257
|
+
return pixel_area / (self.focal_length**2)
|
|
221
258
|
|
|
222
259
|
def get_pixel_shape(self):
|
|
223
260
|
"""
|
|
224
|
-
Get pixel shape code 1, 2 or 3
|
|
261
|
+
Get pixel shape code 1, 2 or 3.
|
|
262
|
+
|
|
263
|
+
Where 1 and 3 are hexagonal pixels, where one is rotated by\
|
|
225
264
|
30 degrees with respect to the other. A square pixel is denoted as 2.
|
|
226
265
|
|
|
227
266
|
Returns
|
|
@@ -229,7 +268,7 @@ class Camera:
|
|
|
229
268
|
int (1, 2 or 3)
|
|
230
269
|
Pixel shape.
|
|
231
270
|
"""
|
|
232
|
-
return self.
|
|
271
|
+
return self.pixels["pixel_shape"]
|
|
233
272
|
|
|
234
273
|
def get_lightguide_efficiency_angle_file_name(self):
|
|
235
274
|
"""
|
|
@@ -240,8 +279,7 @@ class Camera:
|
|
|
240
279
|
str
|
|
241
280
|
File name of the light guide efficiency as a function of incidence angle.
|
|
242
281
|
"""
|
|
243
|
-
|
|
244
|
-
return self._pixels["lightguide_efficiency_angle_file"]
|
|
282
|
+
return self.pixels["lightguide_efficiency_angle_file"]
|
|
245
283
|
|
|
246
284
|
def get_lightguide_efficiency_wavelength_file_name(self):
|
|
247
285
|
"""
|
|
@@ -252,24 +290,26 @@ class Camera:
|
|
|
252
290
|
str
|
|
253
291
|
File name of the light guide efficiency as a function of wavelength.
|
|
254
292
|
"""
|
|
255
|
-
return self.
|
|
293
|
+
return self.pixels["lightguide_efficiency_wavelength_file"]
|
|
256
294
|
|
|
257
295
|
def get_camera_fill_factor(self):
|
|
258
296
|
"""
|
|
259
|
-
Calculate the fill factor of the camera, defined as (pixel_diameter/pixel_spacing)**2
|
|
297
|
+
Calculate the fill factor of the camera, defined as (pixel_diameter/pixel_spacing)**2.
|
|
260
298
|
|
|
261
299
|
Returns
|
|
262
300
|
-------
|
|
263
301
|
float
|
|
264
302
|
The camera fill factor.
|
|
265
303
|
"""
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
points = np.array([self._pixels["x"], self._pixels["y"]]).T
|
|
304
|
+
if self.pixels["pixel_spacing"] == 9999:
|
|
305
|
+
points = np.array([self.pixels["x"], self.pixels["y"]]).T
|
|
269
306
|
pixel_distances = distance.cdist(points, points, "euclidean")
|
|
270
|
-
|
|
307
|
+
# pylint: disable=unsubscriptable-object
|
|
308
|
+
pixel_distances = pixel_distances[pixel_distances > 0]
|
|
309
|
+
pixel_spacing = np.min(pixel_distances)
|
|
310
|
+
self.pixels["pixel_spacing"] = pixel_spacing
|
|
271
311
|
|
|
272
|
-
return (self.
|
|
312
|
+
return (self.pixels["pixel_diameter"] / self.pixels["pixel_spacing"]) ** 2
|
|
273
313
|
|
|
274
314
|
def calc_fov(self):
|
|
275
315
|
"""
|
|
@@ -286,14 +326,13 @@ class Camera:
|
|
|
286
326
|
-----
|
|
287
327
|
The x,y pixel positions and focal length are assumed to have the same unit (usually cm)
|
|
288
328
|
"""
|
|
289
|
-
|
|
290
329
|
self._logger.debug("Calculating the FoV")
|
|
291
330
|
|
|
292
331
|
return self._calc_fov(
|
|
293
|
-
self.
|
|
294
|
-
self.
|
|
332
|
+
self.pixels["x"],
|
|
333
|
+
self.pixels["y"],
|
|
295
334
|
self.get_edge_pixels(),
|
|
296
|
-
self.
|
|
335
|
+
self.focal_length,
|
|
297
336
|
)
|
|
298
337
|
|
|
299
338
|
def _calc_fov(self, x_pixel, y_pixel, edge_pixel_indices, focal_length):
|
|
@@ -323,7 +362,6 @@ class Camera:
|
|
|
323
362
|
-----
|
|
324
363
|
The x,y pixel positions and focal length are assumed to have the same unit (usually cm)
|
|
325
364
|
"""
|
|
326
|
-
|
|
327
365
|
self._logger.debug("Calculating the FoV")
|
|
328
366
|
|
|
329
367
|
average_edge_distance = 0
|
|
@@ -336,10 +374,11 @@ class Camera:
|
|
|
336
374
|
return fov, average_edge_distance
|
|
337
375
|
|
|
338
376
|
@staticmethod
|
|
339
|
-
def
|
|
377
|
+
def _find_neighbors(x_pos, y_pos, radius):
|
|
340
378
|
"""
|
|
341
|
-
|
|
342
|
-
|
|
379
|
+
Use a KD-Tree to quickly find nearest neighbors.
|
|
380
|
+
|
|
381
|
+
This applies to e.g., of the pixels in a camera or mirror facets.
|
|
343
382
|
|
|
344
383
|
Parameters
|
|
345
384
|
----------
|
|
@@ -348,80 +387,101 @@ class Camera:
|
|
|
348
387
|
y_pos : numpy.array_like
|
|
349
388
|
y position of each e.g., pixel
|
|
350
389
|
radius : float
|
|
351
|
-
radius to consider
|
|
390
|
+
radius to consider neighbor it should be slightly larger than the pixel diameter or \
|
|
352
391
|
mirror facet.
|
|
353
392
|
|
|
354
393
|
Returns
|
|
355
394
|
-------
|
|
356
|
-
|
|
357
|
-
Array of
|
|
395
|
+
neighbors: numpy.array_like
|
|
396
|
+
Array of neighbor indices in a list for each e.g., pixel.
|
|
358
397
|
"""
|
|
359
|
-
|
|
360
398
|
points = np.array([x_pos, y_pos]).T
|
|
361
399
|
indices = np.arange(len(x_pos))
|
|
362
400
|
kdtree = KDTree(points)
|
|
363
|
-
|
|
401
|
+
neighbors = [kdtree.query_ball_point(p, r=radius) for p in points]
|
|
364
402
|
|
|
365
|
-
for
|
|
366
|
-
|
|
403
|
+
for neighbor_now, index_now in zip(neighbors, indices):
|
|
404
|
+
neighbor_now.remove(index_now) # get rid of the pixel or mirror itself
|
|
367
405
|
|
|
368
|
-
return
|
|
406
|
+
return neighbors
|
|
369
407
|
|
|
370
|
-
def
|
|
408
|
+
def _find_adjacent_neighbor_pixels(self, x_pos, y_pos, radius, row_column_dist):
|
|
371
409
|
"""
|
|
372
|
-
Find adjacent
|
|
373
|
-
|
|
410
|
+
Find adjacent neighbor pixels in cameras with square pixels.
|
|
411
|
+
|
|
412
|
+
Only directly adjacent neighbors are allowed, no diagonals.
|
|
374
413
|
|
|
375
414
|
Parameters
|
|
376
415
|
----------
|
|
377
416
|
x_pos : numpy.array_like
|
|
378
417
|
x position of each pixel
|
|
379
418
|
y_pos : numpy.array_like
|
|
380
|
-
y position of each
|
|
419
|
+
y position of each pixel
|
|
381
420
|
radius : float
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
neighbour. Should be around 20% of the pixel diameter.
|
|
421
|
+
Radius within which to find neighbors
|
|
422
|
+
row_column_dist : float
|
|
423
|
+
Distance to consider for row/column adjacency.
|
|
424
|
+
Should be around 20% of the pixel diameter.
|
|
387
425
|
|
|
388
426
|
Returns
|
|
389
427
|
-------
|
|
390
|
-
|
|
391
|
-
Array of
|
|
428
|
+
list of lists
|
|
429
|
+
Array of neighbor indices in a list for each pixel
|
|
392
430
|
"""
|
|
431
|
+
# First find the neighbors with the usual method and the original radius
|
|
432
|
+
# which does not allow for diagonal neighbors.
|
|
433
|
+
neighbors = self._find_neighbors(x_pos, y_pos, radius)
|
|
393
434
|
|
|
394
|
-
|
|
395
|
-
# which does not allow for diagonal neighbours.
|
|
396
|
-
neighbours = self._find_neighbours(x_pos, y_pos, radius)
|
|
397
|
-
for i_pix, nn in enumerate(neighbours):
|
|
435
|
+
for i_pix, nn in enumerate(neighbors):
|
|
398
436
|
# Find pixels defined as edge pixels now
|
|
399
437
|
if len(nn) < 4:
|
|
400
438
|
# Go over all other pixels and search for ones which are adjacent
|
|
401
439
|
# but further than sqrt(2) away
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
440
|
+
self._add_additional_neighbors(i_pix, nn, x_pos, y_pos, radius, row_column_dist)
|
|
441
|
+
|
|
442
|
+
return neighbors
|
|
443
|
+
|
|
444
|
+
def _add_additional_neighbors(self, i_pix, nn, x_pos, y_pos, radius, row_column_dist):
|
|
445
|
+
"""
|
|
446
|
+
Add neighbors for a given pixel if they are not already neighbors and are adjacent.
|
|
447
|
+
|
|
448
|
+
Parameters
|
|
449
|
+
----------
|
|
450
|
+
i_pix : int
|
|
451
|
+
Index of the pixel to find neighbors for
|
|
452
|
+
nn : list
|
|
453
|
+
Current list of neighbors for the pixel
|
|
454
|
+
x_pos : numpy.array_like
|
|
455
|
+
x position of each pixel
|
|
456
|
+
y_pos : numpy.array_like
|
|
457
|
+
y position of each pixel
|
|
458
|
+
radius : float
|
|
459
|
+
Radius within which to find neighbors
|
|
460
|
+
row_column_dist : float
|
|
461
|
+
Distance to consider for row/column adjacency
|
|
462
|
+
"""
|
|
463
|
+
for j_pix, _ in enumerate(x_pos):
|
|
464
|
+
# No need to look at the pixel itself
|
|
465
|
+
# nor at any pixels already in the neighbors list
|
|
466
|
+
if j_pix != i_pix and j_pix not in nn:
|
|
467
|
+
dist = np.sqrt(
|
|
468
|
+
(x_pos[i_pix] - x_pos[j_pix]) ** 2 + (y_pos[i_pix] - y_pos[j_pix]) ** 2
|
|
469
|
+
)
|
|
470
|
+
# Check if this pixel is in the same row or column
|
|
471
|
+
# and allow it to be ~1.68*diameter away (1.4*1.2 = 1.68)
|
|
472
|
+
# Need to increase the distance because of the curvature
|
|
473
|
+
# of the CHEC camera
|
|
474
|
+
if (
|
|
475
|
+
abs(x_pos[i_pix] - x_pos[j_pix]) < row_column_dist
|
|
476
|
+
or abs(y_pos[i_pix] - y_pos[j_pix]) < row_column_dist
|
|
477
|
+
) and dist < 1.2 * radius:
|
|
478
|
+
nn.append(j_pix)
|
|
479
|
+
|
|
480
|
+
def _calc_neighbor_pixels(self, pixels):
|
|
481
|
+
"""
|
|
482
|
+
Find adjacent neighbor pixels in cameras with hexagonal or square pixels.
|
|
483
|
+
|
|
484
|
+
Only directly adjacent neighbors are searched for, no diagonals.
|
|
425
485
|
|
|
426
486
|
Parameters
|
|
427
487
|
----------
|
|
@@ -430,14 +490,13 @@ class Camera:
|
|
|
430
490
|
|
|
431
491
|
Returns
|
|
432
492
|
-------
|
|
433
|
-
|
|
434
|
-
Array of
|
|
493
|
+
neighbors: numpy.array_like
|
|
494
|
+
Array of neighbor indices in a list for each pixel
|
|
435
495
|
"""
|
|
436
|
-
|
|
437
|
-
self._logger.debug("Searching for neighbour pixels")
|
|
496
|
+
self._logger.debug("Searching for neighbor pixels")
|
|
438
497
|
|
|
439
498
|
if pixels["pixel_shape"] == 1 or pixels["pixel_shape"] == 3:
|
|
440
|
-
self.
|
|
499
|
+
self._neighbors = self._find_neighbors(
|
|
441
500
|
pixels["x"],
|
|
442
501
|
pixels["y"],
|
|
443
502
|
self.PMT_NEIGHBOR_RADIUS_FACTOR * pixels["pixel_diameter"],
|
|
@@ -445,21 +504,22 @@ class Camera:
|
|
|
445
504
|
elif pixels["pixel_shape"] == 2:
|
|
446
505
|
# Distance increased by 40% to take into account gaps in the SiPM cameras
|
|
447
506
|
# Pixels in the same row/column can be 20% shifted from one another
|
|
448
|
-
# Inside
|
|
507
|
+
# Inside find_adjacent_neighbor_pixels the distance is increased
|
|
449
508
|
# further for pixels in the same row/column to 1.68*diameter.
|
|
450
|
-
self.
|
|
509
|
+
self._neighbors = self._find_adjacent_neighbor_pixels(
|
|
451
510
|
pixels["x"],
|
|
452
511
|
pixels["y"],
|
|
453
512
|
self.SIPM_NEIGHBOR_RADIUS_FACTOR * pixels["pixel_diameter"],
|
|
454
513
|
self.SIPM_ROW_COLUMN_DIST_FACTOR * pixels["pixel_diameter"],
|
|
455
514
|
)
|
|
456
515
|
|
|
457
|
-
return self.
|
|
516
|
+
return self._neighbors
|
|
458
517
|
|
|
459
|
-
def
|
|
518
|
+
def get_neighbor_pixels(self, pixels=None):
|
|
460
519
|
"""
|
|
461
|
-
Get a list of
|
|
462
|
-
|
|
520
|
+
Get a list of neighbor pixels by calling calc_neighbor_pixels() when necessary.
|
|
521
|
+
|
|
522
|
+
The purpose of this function is to ensure the calculation occurs only once and only when
|
|
463
523
|
necessary.
|
|
464
524
|
|
|
465
525
|
Parameters
|
|
@@ -469,18 +529,17 @@ class Camera:
|
|
|
469
529
|
|
|
470
530
|
Returns
|
|
471
531
|
-------
|
|
472
|
-
|
|
473
|
-
Array of
|
|
532
|
+
neighbors: numpy.array_like
|
|
533
|
+
Array of neighbor indices in a list for each pixel.
|
|
474
534
|
"""
|
|
475
|
-
|
|
476
|
-
if self._neighbours is None:
|
|
535
|
+
if self._neighbors is None:
|
|
477
536
|
if pixels is None:
|
|
478
|
-
pixels = self.
|
|
479
|
-
return self.
|
|
537
|
+
pixels = self.pixels
|
|
538
|
+
return self._calc_neighbor_pixels(pixels)
|
|
480
539
|
|
|
481
|
-
return self.
|
|
540
|
+
return self._neighbors
|
|
482
541
|
|
|
483
|
-
def _calc_edge_pixels(self, pixels,
|
|
542
|
+
def _calc_edge_pixels(self, pixels, neighbors):
|
|
484
543
|
"""
|
|
485
544
|
Find the edge pixels of the camera.
|
|
486
545
|
|
|
@@ -488,32 +547,34 @@ class Camera:
|
|
|
488
547
|
----------
|
|
489
548
|
pixels: dictionary
|
|
490
549
|
The dictionary produced by the read_pixel_list method of this class.
|
|
491
|
-
|
|
492
|
-
Array of
|
|
550
|
+
neighbors: numpy.array_like
|
|
551
|
+
Array of neighbor indices in a list for each pixel.
|
|
493
552
|
|
|
494
553
|
Returns
|
|
495
554
|
-------
|
|
496
555
|
edge_pixel_indices: numpy.array_like
|
|
497
556
|
Array of edge pixel indices.
|
|
498
557
|
"""
|
|
499
|
-
|
|
500
558
|
self._logger.debug("Searching for edge pixels")
|
|
501
|
-
|
|
502
559
|
edge_pixel_indices = []
|
|
503
560
|
|
|
561
|
+
def is_edge_pixel(i_pix):
|
|
562
|
+
pixel_shape = pixels["pixel_shape"]
|
|
563
|
+
pix_on = pixels["pix_on"][i_pix]
|
|
564
|
+
num_neighbors = len(neighbors[i_pix])
|
|
565
|
+
|
|
566
|
+
shape_condition = (pixel_shape in [1, 3] and num_neighbors < 6) or (
|
|
567
|
+
pixel_shape == 2 and num_neighbors < 4
|
|
568
|
+
)
|
|
569
|
+
return pix_on and shape_condition
|
|
570
|
+
|
|
504
571
|
for i_pix, _ in enumerate(pixels["x"]):
|
|
505
|
-
if
|
|
506
|
-
|
|
507
|
-
if len(neighbours[i_pix]) < 6:
|
|
508
|
-
edge_pixel_indices.append(i_pix)
|
|
509
|
-
elif pixels["pixel_shape"] == 2:
|
|
510
|
-
if pixels["pix_on"][i_pix]:
|
|
511
|
-
if len(neighbours[i_pix]) < 4:
|
|
512
|
-
edge_pixel_indices.append(i_pix)
|
|
572
|
+
if is_edge_pixel(i_pix):
|
|
573
|
+
edge_pixel_indices.append(i_pix)
|
|
513
574
|
|
|
514
575
|
return edge_pixel_indices
|
|
515
576
|
|
|
516
|
-
def get_edge_pixels(self, pixels=None,
|
|
577
|
+
def get_edge_pixels(self, pixels=None, neighbors=None):
|
|
517
578
|
"""
|
|
518
579
|
Get the indices of the edge pixels of the camera.
|
|
519
580
|
|
|
@@ -521,340 +582,19 @@ class Camera:
|
|
|
521
582
|
----------
|
|
522
583
|
pixels: dict
|
|
523
584
|
The dictionary produced by the read_pixel_list method of this class.
|
|
524
|
-
|
|
525
|
-
Array of
|
|
585
|
+
neighbors: numpy.array_like
|
|
586
|
+
Array of neighbor indices in a list for each pixel.
|
|
526
587
|
|
|
527
588
|
Returns
|
|
528
589
|
-------
|
|
529
590
|
edge_pixel_indices: numpy.array_like
|
|
530
591
|
Array of edge pixel indices.
|
|
531
592
|
"""
|
|
532
|
-
|
|
533
593
|
if self._edge_pixel_indices is None:
|
|
534
594
|
if pixels is None:
|
|
535
|
-
pixels = self.
|
|
536
|
-
if
|
|
537
|
-
|
|
538
|
-
return self._calc_edge_pixels(pixels,
|
|
595
|
+
pixels = self.pixels
|
|
596
|
+
if neighbors is None:
|
|
597
|
+
neighbors = self.get_neighbor_pixels()
|
|
598
|
+
return self._calc_edge_pixels(pixels, neighbors)
|
|
539
599
|
|
|
540
600
|
return self._edge_pixel_indices
|
|
541
|
-
|
|
542
|
-
def _plot_axes_def(self, plot, rotate_angle):
|
|
543
|
-
"""
|
|
544
|
-
Plot three axes definitions on the pyplot.plt instance provided. The three axes are Alt/Az,\
|
|
545
|
-
the camera coordinate system and the original coordinate system the pixel list was provided.
|
|
546
|
-
|
|
547
|
-
Parameters
|
|
548
|
-
----------
|
|
549
|
-
plot: pyplot.plt instance
|
|
550
|
-
A pyplot.plt instance where to add the axes definitions.
|
|
551
|
-
rotate_angle: float
|
|
552
|
-
The rotation angle applied
|
|
553
|
-
"""
|
|
554
|
-
|
|
555
|
-
invert_yaxis = False
|
|
556
|
-
x_left = 0.7 # Position of the left most axis
|
|
557
|
-
if not is_two_mirror_telescope(self._telescope_model_name):
|
|
558
|
-
invert_yaxis = True
|
|
559
|
-
x_left = 0.8
|
|
560
|
-
|
|
561
|
-
x_title = r"$x_{\!pix}$"
|
|
562
|
-
y_title = r"$y_{\!pix}$"
|
|
563
|
-
x_pos, y_pos = (x_left, 0.12)
|
|
564
|
-
# The rotation of LST (above 100 degrees) raises the axes.
|
|
565
|
-
# In this case, lower the starting point.
|
|
566
|
-
if np.rad2deg(rotate_angle) > 100:
|
|
567
|
-
y_pos -= 0.09
|
|
568
|
-
x_pos -= 0.05
|
|
569
|
-
kwargs = {
|
|
570
|
-
"x_title": x_title,
|
|
571
|
-
"y_title": y_title,
|
|
572
|
-
"x_pos": x_pos,
|
|
573
|
-
"y_pos": y_pos,
|
|
574
|
-
"rotate_angle": rotate_angle - (1 / 2.0) * np.pi,
|
|
575
|
-
"fc": "black",
|
|
576
|
-
"ec": "black",
|
|
577
|
-
"invert_yaxis": invert_yaxis,
|
|
578
|
-
}
|
|
579
|
-
self._plot_one_axis_def(plot, **kwargs)
|
|
580
|
-
|
|
581
|
-
x_title = r"$x_{\!cam}$"
|
|
582
|
-
y_title = r"$y_{\!cam}$"
|
|
583
|
-
x_pos, y_pos = (x_left + 0.15, 0.12)
|
|
584
|
-
kwargs = {
|
|
585
|
-
"x_title": x_title,
|
|
586
|
-
"y_title": y_title,
|
|
587
|
-
"x_pos": x_pos,
|
|
588
|
-
"y_pos": y_pos,
|
|
589
|
-
"rotate_angle": (3 / 2.0) * np.pi,
|
|
590
|
-
"fc": "blue",
|
|
591
|
-
"ec": "blue",
|
|
592
|
-
"invert_yaxis": invert_yaxis,
|
|
593
|
-
}
|
|
594
|
-
self._plot_one_axis_def(plot, **kwargs)
|
|
595
|
-
|
|
596
|
-
x_title = "Alt"
|
|
597
|
-
y_title = "Az"
|
|
598
|
-
x_pos, y_pos = (x_left + 0.15, 0.25)
|
|
599
|
-
kwargs = {
|
|
600
|
-
"x_title": x_title,
|
|
601
|
-
"y_title": y_title,
|
|
602
|
-
"x_pos": x_pos,
|
|
603
|
-
"y_pos": y_pos,
|
|
604
|
-
"rotate_angle": (3 / 2.0) * np.pi,
|
|
605
|
-
"fc": "red",
|
|
606
|
-
"ec": "red",
|
|
607
|
-
"invert_yaxis": invert_yaxis,
|
|
608
|
-
}
|
|
609
|
-
self._plot_one_axis_def(plot, **kwargs)
|
|
610
|
-
|
|
611
|
-
@staticmethod
|
|
612
|
-
def _plot_one_axis_def(plot, **kwargs):
|
|
613
|
-
"""
|
|
614
|
-
Plot an axis on the pyplot.plt instance provided.
|
|
615
|
-
|
|
616
|
-
Parameters
|
|
617
|
-
----------
|
|
618
|
-
plot: pyplot.plt instance
|
|
619
|
-
A pyplot.plt instance where to add the axes definitions.
|
|
620
|
-
**kwargs: dict
|
|
621
|
-
x_title: str
|
|
622
|
-
x-axis title
|
|
623
|
-
y_title: str
|
|
624
|
-
y-axis title,
|
|
625
|
-
x_pos: float
|
|
626
|
-
x position of the axis to draw
|
|
627
|
-
y_pos: float
|
|
628
|
-
y position of the axis to draw
|
|
629
|
-
rotate_angle: float
|
|
630
|
-
rotation angle of the axis in radians
|
|
631
|
-
fc: str
|
|
632
|
-
face colour of the axis
|
|
633
|
-
ec: str
|
|
634
|
-
edge colour of the axis
|
|
635
|
-
invert_yaxis: bool
|
|
636
|
-
Flag to invert the y-axis (for dual mirror telescopes).
|
|
637
|
-
"""
|
|
638
|
-
|
|
639
|
-
x_title = kwargs["x_title"]
|
|
640
|
-
y_title = kwargs["y_title"]
|
|
641
|
-
x_pos, y_pos = (kwargs["x_pos"], kwargs["y_pos"])
|
|
642
|
-
|
|
643
|
-
r = 0.1 # size of arrow
|
|
644
|
-
sign = 1.0
|
|
645
|
-
if kwargs["invert_yaxis"]:
|
|
646
|
-
sign *= -1.0
|
|
647
|
-
x_text1 = x_pos + sign * r * np.cos(kwargs["rotate_angle"])
|
|
648
|
-
y_text1 = y_pos + r * np.sin(0 + kwargs["rotate_angle"])
|
|
649
|
-
x_text2 = x_pos + sign * r * np.cos(np.pi / 2.0 + kwargs["rotate_angle"])
|
|
650
|
-
y_text2 = y_pos + r * np.sin(np.pi / 2.0 + kwargs["rotate_angle"])
|
|
651
|
-
|
|
652
|
-
plot.gca().annotate(
|
|
653
|
-
x_title,
|
|
654
|
-
xy=(x_pos, y_pos),
|
|
655
|
-
xytext=(x_text1, y_text1),
|
|
656
|
-
xycoords="axes fraction",
|
|
657
|
-
ha="center",
|
|
658
|
-
va="center",
|
|
659
|
-
size="xx-large",
|
|
660
|
-
arrowprops={
|
|
661
|
-
"arrowstyle": "<|-",
|
|
662
|
-
"shrinkA": 0,
|
|
663
|
-
"shrinkB": 0,
|
|
664
|
-
"fc": kwargs["fc"],
|
|
665
|
-
"ec": kwargs["ec"],
|
|
666
|
-
},
|
|
667
|
-
)
|
|
668
|
-
|
|
669
|
-
plot.gca().annotate(
|
|
670
|
-
y_title,
|
|
671
|
-
xy=(x_pos, y_pos),
|
|
672
|
-
xytext=(x_text2, y_text2),
|
|
673
|
-
xycoords="axes fraction",
|
|
674
|
-
ha="center",
|
|
675
|
-
va="center",
|
|
676
|
-
size="xx-large",
|
|
677
|
-
arrowprops={
|
|
678
|
-
"arrowstyle": "<|-",
|
|
679
|
-
"shrinkA": 0,
|
|
680
|
-
"shrinkB": 0,
|
|
681
|
-
"fc": kwargs["fc"],
|
|
682
|
-
"ec": kwargs["ec"],
|
|
683
|
-
},
|
|
684
|
-
)
|
|
685
|
-
|
|
686
|
-
def plot_pixel_layout(self, camera_in_sky_coor=False, pixels_id_to_print=50):
|
|
687
|
-
"""
|
|
688
|
-
Plot the pixel layout for an observer facing the camera. Including in the plot edge pixels,\
|
|
689
|
-
off pixels, pixel ID for the first 50 pixels, coordinate systems, FOV, focal length and the\
|
|
690
|
-
average edge radius.
|
|
691
|
-
|
|
692
|
-
Returns
|
|
693
|
-
-------
|
|
694
|
-
fig: plt.figure instance
|
|
695
|
-
Figure with the pixel layout.
|
|
696
|
-
"""
|
|
697
|
-
|
|
698
|
-
self._logger.info(f"Plotting the {self._telescope_model_name} camera")
|
|
699
|
-
|
|
700
|
-
fig, ax = plt.subplots()
|
|
701
|
-
plt.gcf().set_size_inches(8, 8)
|
|
702
|
-
|
|
703
|
-
if not is_two_mirror_telescope(self._telescope_model_name):
|
|
704
|
-
if not camera_in_sky_coor:
|
|
705
|
-
self._pixels["y"] = [(-1) * y_val for y_val in self._pixels["y"]]
|
|
706
|
-
|
|
707
|
-
on_pixels, edge_pixels, off_pixels = [], [], []
|
|
708
|
-
|
|
709
|
-
for i_pix, xy_pix_pos in enumerate(zip(self._pixels["x"], self._pixels["y"])):
|
|
710
|
-
if self._pixels["pixel_shape"] == 1 or self._pixels["pixel_shape"] == 3:
|
|
711
|
-
hexagon = mpatches.RegularPolygon(
|
|
712
|
-
(xy_pix_pos[0], xy_pix_pos[1]),
|
|
713
|
-
numVertices=6,
|
|
714
|
-
radius=self._pixels["pixel_diameter"] / np.sqrt(3),
|
|
715
|
-
orientation=np.deg2rad(self._pixels["orientation"]),
|
|
716
|
-
)
|
|
717
|
-
if self._pixels["pix_on"][i_pix]:
|
|
718
|
-
if len(self.get_neighbour_pixels()[i_pix]) < 6:
|
|
719
|
-
edge_pixels.append(hexagon)
|
|
720
|
-
else:
|
|
721
|
-
on_pixels.append(hexagon)
|
|
722
|
-
else:
|
|
723
|
-
off_pixels.append(hexagon)
|
|
724
|
-
elif self._pixels["pixel_shape"] == 2:
|
|
725
|
-
square = mpatches.Rectangle(
|
|
726
|
-
(
|
|
727
|
-
xy_pix_pos[0] - self._pixels["pixel_diameter"] / 2.0,
|
|
728
|
-
xy_pix_pos[1] - self._pixels["pixel_diameter"] / 2.0,
|
|
729
|
-
),
|
|
730
|
-
width=self._pixels["pixel_diameter"],
|
|
731
|
-
height=self._pixels["pixel_diameter"],
|
|
732
|
-
)
|
|
733
|
-
if self._pixels["pix_on"][i_pix]:
|
|
734
|
-
if len(self.get_neighbour_pixels()[i_pix]) < 4:
|
|
735
|
-
edge_pixels.append(square)
|
|
736
|
-
else:
|
|
737
|
-
on_pixels.append(square)
|
|
738
|
-
else:
|
|
739
|
-
off_pixels.append(square)
|
|
740
|
-
|
|
741
|
-
if self._pixels["pix_id"][i_pix] < pixels_id_to_print + 1:
|
|
742
|
-
font_size = 4
|
|
743
|
-
if names.get_telescope_class(self._telescope_model_name) == "SCT":
|
|
744
|
-
font_size = 2
|
|
745
|
-
plt.text(
|
|
746
|
-
xy_pix_pos[0],
|
|
747
|
-
xy_pix_pos[1],
|
|
748
|
-
self._pixels["pix_id"][i_pix],
|
|
749
|
-
horizontalalignment="center",
|
|
750
|
-
verticalalignment="center",
|
|
751
|
-
fontsize=font_size,
|
|
752
|
-
)
|
|
753
|
-
|
|
754
|
-
ax.add_collection(
|
|
755
|
-
PatchCollection(on_pixels, facecolor="none", edgecolor="black", linewidth=0.2)
|
|
756
|
-
)
|
|
757
|
-
ax.add_collection(
|
|
758
|
-
PatchCollection(
|
|
759
|
-
edge_pixels,
|
|
760
|
-
facecolor=mcolors.to_rgb("brown") + (0.5,),
|
|
761
|
-
edgecolor=mcolors.to_rgb("black") + (1,),
|
|
762
|
-
linewidth=0.2,
|
|
763
|
-
)
|
|
764
|
-
)
|
|
765
|
-
ax.add_collection(
|
|
766
|
-
PatchCollection(off_pixels, facecolor="black", edgecolor="black", linewidth=0.2)
|
|
767
|
-
)
|
|
768
|
-
|
|
769
|
-
legend_objects = [leg_h.PixelObject(), leg_h.EdgePixelObject()]
|
|
770
|
-
legend_labels = ["Pixel", "Edge pixel"]
|
|
771
|
-
if isinstance(on_pixels[0], mlp.patches.RegularPolygon):
|
|
772
|
-
legend_handler_map = {
|
|
773
|
-
leg_h.PixelObject: leg_h.HexPixelHandler(),
|
|
774
|
-
leg_h.EdgePixelObject: leg_h.HexEdgePixelHandler(),
|
|
775
|
-
leg_h.OffPixelObject: leg_h.HexOffPixelHandler(),
|
|
776
|
-
}
|
|
777
|
-
elif isinstance(on_pixels[0], mlp.patches.Rectangle):
|
|
778
|
-
legend_handler_map = {
|
|
779
|
-
leg_h.PixelObject: leg_h.SquarePixelHandler(),
|
|
780
|
-
leg_h.EdgePixelObject: leg_h.SquareEdgePixelHandler(),
|
|
781
|
-
leg_h.OffPixelObject: leg_h.SquareOffPixelHandler(),
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
if len(off_pixels) > 0:
|
|
785
|
-
legend_objects.append(leg_h.OffPixelObject())
|
|
786
|
-
legend_labels.append("Disabled pixel")
|
|
787
|
-
|
|
788
|
-
plt.axis("equal")
|
|
789
|
-
plt.grid(True)
|
|
790
|
-
ax.set_axisbelow(True)
|
|
791
|
-
plt.axis(
|
|
792
|
-
[
|
|
793
|
-
min(self._pixels["x"]),
|
|
794
|
-
max(self._pixels["x"]),
|
|
795
|
-
min(self._pixels["y"]) * 1.42,
|
|
796
|
-
max(self._pixels["y"]) * 1.42,
|
|
797
|
-
]
|
|
798
|
-
)
|
|
799
|
-
plt.xlabel("Horizontal scale [cm]", fontsize=18, labelpad=0)
|
|
800
|
-
plt.ylabel("Vertical scale [cm]", fontsize=18, labelpad=0)
|
|
801
|
-
ax.set_title(
|
|
802
|
-
f"Pixels layout in {self._telescope_model_name:s} camera",
|
|
803
|
-
fontsize=15,
|
|
804
|
-
y=1.02,
|
|
805
|
-
)
|
|
806
|
-
plt.tick_params(axis="both", which="major", labelsize=15)
|
|
807
|
-
|
|
808
|
-
self._plot_axes_def(plt, self._pixels["rotate_angle"])
|
|
809
|
-
description = "For an observer facing the camera"
|
|
810
|
-
if camera_in_sky_coor and not is_two_mirror_telescope(self._telescope_model_name):
|
|
811
|
-
description = "For an observer behind the camera looking through"
|
|
812
|
-
if is_two_mirror_telescope(self._telescope_model_name):
|
|
813
|
-
description = "For an observer looking from secondary to camera"
|
|
814
|
-
ax.text(
|
|
815
|
-
0.02,
|
|
816
|
-
0.02,
|
|
817
|
-
description,
|
|
818
|
-
transform=ax.transAxes,
|
|
819
|
-
color="black",
|
|
820
|
-
fontsize=12,
|
|
821
|
-
)
|
|
822
|
-
|
|
823
|
-
fov, r_edge_avg = self.calc_fov()
|
|
824
|
-
ax.text(
|
|
825
|
-
0.02,
|
|
826
|
-
0.96,
|
|
827
|
-
r"$f_{\mathrm{eff}}$ = " + f"{self._focal_length:.3f} cm",
|
|
828
|
-
transform=ax.transAxes,
|
|
829
|
-
color="black",
|
|
830
|
-
fontsize=12,
|
|
831
|
-
)
|
|
832
|
-
ax.text(
|
|
833
|
-
0.02,
|
|
834
|
-
0.92,
|
|
835
|
-
f"Avg. edge radius = {r_edge_avg:.3f} cm",
|
|
836
|
-
transform=ax.transAxes,
|
|
837
|
-
color="black",
|
|
838
|
-
fontsize=12,
|
|
839
|
-
)
|
|
840
|
-
ax.text(
|
|
841
|
-
0.02,
|
|
842
|
-
0.88,
|
|
843
|
-
f"FoV = {fov:.3f} deg",
|
|
844
|
-
transform=ax.transAxes,
|
|
845
|
-
color="black",
|
|
846
|
-
fontsize=12,
|
|
847
|
-
)
|
|
848
|
-
|
|
849
|
-
plt.legend(
|
|
850
|
-
legend_objects,
|
|
851
|
-
legend_labels,
|
|
852
|
-
handler_map=legend_handler_map,
|
|
853
|
-
prop={"size": 11},
|
|
854
|
-
loc="upper right",
|
|
855
|
-
)
|
|
856
|
-
|
|
857
|
-
ax.set_aspect("equal", "datalim")
|
|
858
|
-
plt.tight_layout()
|
|
859
|
-
|
|
860
|
-
return fig
|