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