gammasimtools 0.25.0__py3-none-any.whl → 0.27.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/METADATA +6 -1
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/RECORD +135 -130
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/WHEEL +1 -1
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/entry_points.txt +3 -2
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/licenses/LICENSE +1 -1
- simtools/_version.py +2 -2
- simtools/application_control.py +35 -7
- simtools/applications/convert_geo_coordinates_of_array_elements.py +3 -3
- simtools/applications/db_add_file_to_db.py +1 -1
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +1 -1
- simtools/applications/db_add_value_from_json_to_db.py +1 -1
- simtools/applications/db_generate_compound_indexes.py +1 -1
- simtools/applications/db_get_array_layouts_from_db.py +3 -7
- simtools/applications/db_get_file_from_db.py +1 -1
- simtools/applications/db_get_parameter_from_db.py +1 -1
- simtools/applications/db_inspect_databases.py +1 -1
- simtools/applications/db_upload_model_repository.py +1 -1
- simtools/applications/derive_ctao_array_layouts.py +1 -2
- simtools/applications/{calculate_incident_angles.py → derive_incident_angle.py} +16 -18
- simtools/applications/derive_mirror_rnda.py +112 -180
- simtools/applications/derive_psf_parameters.py +0 -1
- simtools/applications/derive_pulse_shape_parameters.py +0 -1
- simtools/applications/derive_trigger_rates.py +1 -1
- simtools/applications/docs_produce_array_element_report.py +2 -8
- simtools/applications/docs_produce_calibration_reports.py +1 -3
- simtools/applications/docs_produce_model_parameter_reports.py +0 -2
- simtools/applications/docs_produce_simulation_configuration_report.py +1 -3
- simtools/applications/generate_array_config.py +0 -1
- simtools/applications/generate_corsika_histograms.py +79 -229
- simtools/applications/generate_regular_arrays.py +76 -69
- simtools/applications/generate_simtel_event_data.py +2 -2
- simtools/applications/maintain_simulation_model_add_production.py +2 -2
- simtools/applications/maintain_simulation_model_write_array_element_positions.py +87 -0
- simtools/applications/plot_array_layout.py +5 -111
- simtools/applications/plot_simulated_event_distributions.py +57 -0
- simtools/applications/plot_tabular_data.py +0 -1
- simtools/applications/plot_tabular_data_for_model_parameter.py +1 -6
- simtools/applications/production_derive_corsika_limits.py +1 -1
- simtools/applications/production_generate_grid.py +0 -1
- simtools/applications/run_application.py +1 -1
- simtools/applications/simulate_flasher.py +3 -15
- simtools/applications/simulate_illuminator.py +2 -11
- simtools/applications/simulate_pedestals.py +1 -5
- simtools/applications/simulate_prod.py +8 -11
- simtools/applications/simulate_prod_htcondor_generator.py +1 -1
- simtools/applications/submit_array_layouts.py +2 -4
- simtools/applications/submit_data_from_external.py +2 -1
- simtools/applications/submit_model_parameter_from_external.py +1 -3
- simtools/applications/validate_camera_efficiency.py +28 -28
- simtools/applications/validate_camera_fov.py +0 -1
- simtools/applications/validate_cumulative_psf.py +1 -5
- simtools/applications/validate_optics.py +2 -14
- simtools/atmosphere.py +83 -0
- simtools/camera/camera_efficiency.py +171 -53
- simtools/camera/single_photon_electron_spectrum.py +8 -7
- simtools/configuration/commandline_parser.py +82 -11
- simtools/configuration/configurator.py +6 -11
- simtools/constants.py +5 -0
- simtools/corsika/corsika_config.py +100 -202
- simtools/corsika/corsika_histograms.py +561 -1708
- simtools/corsika/primary_particle.py +1 -1
- simtools/data_model/metadata_collector.py +5 -2
- simtools/data_model/metadata_model.py +0 -4
- simtools/data_model/model_data_writer.py +59 -64
- simtools/data_model/schema.py +2 -0
- simtools/data_model/validate_data.py +1 -3
- simtools/db/db_handler.py +23 -10
- simtools/db/mongo_db.py +2 -2
- simtools/dependencies.py +81 -38
- simtools/io/ascii_handler.py +55 -5
- simtools/io/io_handler.py +23 -12
- simtools/io/table_handler.py +1 -1
- simtools/job_execution/job_manager.py +154 -79
- simtools/job_execution/process_pool.py +137 -0
- simtools/layout/array_layout.py +4 -13
- simtools/layout/array_layout_utils.py +348 -57
- simtools/model/array_model.py +23 -63
- simtools/model/calibration_model.py +4 -8
- simtools/model/legacy_model_parameter.py +134 -0
- simtools/model/model_parameter.py +147 -86
- simtools/model/model_utils.py +40 -6
- simtools/model/site_model.py +4 -8
- simtools/model/telescope_model.py +10 -16
- simtools/production_configuration/derive_corsika_limits.py +6 -11
- simtools/production_configuration/interpolation_handler.py +16 -16
- simtools/ray_tracing/incident_angles.py +92 -17
- simtools/ray_tracing/mirror_panel_psf.py +338 -222
- simtools/ray_tracing/psf_analysis.py +62 -48
- simtools/ray_tracing/psf_parameter_optimisation.py +3 -3
- simtools/ray_tracing/ray_tracing.py +43 -25
- simtools/reporting/docs_auto_report_generator.py +8 -13
- simtools/reporting/docs_read_parameters.py +2 -8
- simtools/runners/corsika_runner.py +52 -195
- simtools/runners/corsika_simtel_runner.py +77 -108
- simtools/runners/runner_services.py +214 -213
- simtools/runners/simtel_runner.py +27 -160
- simtools/runners/simtools_runner.py +11 -73
- simtools/schemas/application_workflow.metaschema.yml +8 -0
- simtools/settings.py +173 -0
- simtools/{io/eventio_handler.py → sim_events/file_info.py} +3 -3
- simtools/{simtel/simtel_io_event_histograms.py → sim_events/histograms.py} +25 -15
- simtools/{simtel/simtel_io_event_reader.py → sim_events/reader.py} +20 -17
- simtools/{simtel/simtel_io_event_writer.py → sim_events/writer.py} +84 -25
- simtools/simtel/pulse_shapes.py +7 -2
- simtools/simtel/simtel_config_writer.py +79 -91
- simtools/simtel/simtel_seeds.py +184 -0
- simtools/simtel/simtel_table_reader.py +6 -4
- simtools/simtel/simulator_array.py +114 -109
- simtools/simtel/simulator_camera_efficiency.py +68 -46
- simtools/simtel/simulator_light_emission.py +164 -132
- simtools/simtel/simulator_ray_tracing.py +80 -71
- simtools/simulator.py +137 -355
- simtools/telescope_trigger_rates.py +3 -4
- simtools/testing/assertions.py +84 -33
- simtools/testing/configuration.py +1 -2
- simtools/testing/helpers.py +2 -3
- simtools/testing/log_inspector.py +1 -0
- simtools/testing/sim_telarray_metadata.py +14 -12
- simtools/testing/validate_output.py +121 -42
- simtools/utils/general.py +43 -17
- simtools/utils/geometry.py +0 -77
- simtools/utils/names.py +5 -5
- simtools/utils/random.py +36 -0
- simtools/visualization/legend_handlers.py +7 -6
- simtools/visualization/plot_array_layout.py +91 -16
- simtools/visualization/plot_corsika_histograms.py +145 -605
- simtools/visualization/plot_incident_angles.py +48 -1
- simtools/visualization/plot_mirrors.py +1 -4
- simtools/visualization/plot_pixels.py +2 -4
- simtools/visualization/plot_psf.py +160 -19
- simtools/visualization/plot_simtel_event_histograms.py +4 -4
- simtools/visualization/plot_simtel_events.py +6 -11
- simtools/visualization/plot_tables.py +8 -19
- simtools/visualization/visualize.py +22 -2
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +0 -160
- simtools/applications/print_version.py +0 -53
- simtools/io/hdf5_handler.py +0 -139
- {gammasimtools-0.25.0.dist-info → gammasimtools-0.27.0.dist-info}/top_level.txt +0 -0
simtools/utils/geometry.py
CHANGED
|
@@ -1,88 +1,11 @@
|
|
|
1
1
|
"""A collection of functions related to geometrical transformations."""
|
|
2
2
|
|
|
3
|
-
import logging
|
|
4
3
|
import math
|
|
5
4
|
|
|
6
5
|
import astropy.units as u
|
|
7
6
|
import numpy as np
|
|
8
7
|
from astropy.units import UnitsError
|
|
9
8
|
|
|
10
|
-
_logger = logging.getLogger(__name__)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def convert_2d_to_radial_distr(hist_2d, xaxis, yaxis, bins=50, max_dist=1000):
|
|
14
|
-
"""
|
|
15
|
-
Convert a 2d histogram of positions, e.g. photon positions on the ground, to a 1D distribution.
|
|
16
|
-
|
|
17
|
-
Parameters
|
|
18
|
-
----------
|
|
19
|
-
hist_2d: numpy.ndarray
|
|
20
|
-
The histogram counts.
|
|
21
|
-
xaxis: numpy.array
|
|
22
|
-
The values of the x axis (histogram bin edges) on the ground.
|
|
23
|
-
yaxis: numpy.array
|
|
24
|
-
The values of the y axis (histogram bin edges) on the ground.
|
|
25
|
-
bins: float
|
|
26
|
-
Number of bins in distance.
|
|
27
|
-
max_dist: float
|
|
28
|
-
Maximum distance to consider in the 1D histogram, usually in meters.
|
|
29
|
-
|
|
30
|
-
Returns
|
|
31
|
-
-------
|
|
32
|
-
np.array
|
|
33
|
-
The values of the 1D histogram with size = int(max_dist/bin_size).
|
|
34
|
-
np.array
|
|
35
|
-
The bin edges of the 1D histogram with size = int(max_dist/bin_size) + 1.
|
|
36
|
-
|
|
37
|
-
"""
|
|
38
|
-
# Check if the histogram will make sense
|
|
39
|
-
bins_step = 2 * max_dist / bins # in the 2d array, the positive and negative direction count.
|
|
40
|
-
for axis in [xaxis, yaxis]:
|
|
41
|
-
if (bins_step < np.diff(axis)).any():
|
|
42
|
-
msg = (
|
|
43
|
-
f"The histogram with number of bins {bins} and maximum distance of {max_dist} "
|
|
44
|
-
f"resulted in a bin size smaller than the original array. Please adjust those "
|
|
45
|
-
f"parameters to increase the bin size and avoid nan in the histogram values."
|
|
46
|
-
)
|
|
47
|
-
_logger.warning(msg)
|
|
48
|
-
break
|
|
49
|
-
|
|
50
|
-
grid_2d_x, grid_2d_y = np.meshgrid(xaxis[:-1], yaxis[:-1]) # [:-1], since xaxis and yaxis are
|
|
51
|
-
# the hist bin_edges (n + 1).
|
|
52
|
-
# radial_distance_map maps the distance to the center from each element in a square matrix.
|
|
53
|
-
radial_distance_map = np.sqrt(grid_2d_x**2 + grid_2d_y**2)
|
|
54
|
-
# The sorting and unravel_index give us the two indices for the position of the sorted element
|
|
55
|
-
# in the original 2d matrix
|
|
56
|
-
sorted_indices = np.unravel_index(
|
|
57
|
-
np.argsort(radial_distance_map, axis=None), np.shape(radial_distance_map)
|
|
58
|
-
)
|
|
59
|
-
x_indices_sorted, y_indices_sorted = sorted_indices[0], sorted_indices[1]
|
|
60
|
-
|
|
61
|
-
# We construct a 1D array with the histogram counts sorted according to the distance to the
|
|
62
|
-
# center.
|
|
63
|
-
hist_sorted = np.array(
|
|
64
|
-
[hist_2d[i_x, i_y] for i_x, i_y in zip(x_indices_sorted, y_indices_sorted)]
|
|
65
|
-
)
|
|
66
|
-
distance_sorted = np.sort(radial_distance_map, axis=None)
|
|
67
|
-
|
|
68
|
-
# For larger distances, we have more elements in a slice 'dr' in radius, hence, we need to
|
|
69
|
-
# account for it using weights below.
|
|
70
|
-
|
|
71
|
-
weights, radial_bin_edges = np.histogram(distance_sorted, bins=bins, range=(0, max_dist))
|
|
72
|
-
histogram_1d = np.empty_like(weights, dtype=float)
|
|
73
|
-
|
|
74
|
-
for i_radial, _ in enumerate(radial_bin_edges[:-1]):
|
|
75
|
-
# Here we sum all the events within a radial interval 'dr' and then divide by the number of
|
|
76
|
-
# bins that fit this interval.
|
|
77
|
-
indices_to_sum = (distance_sorted >= radial_bin_edges[i_radial]) * (
|
|
78
|
-
distance_sorted < radial_bin_edges[i_radial + 1]
|
|
79
|
-
)
|
|
80
|
-
if weights[i_radial] != 0:
|
|
81
|
-
histogram_1d[i_radial] = np.sum(hist_sorted[indices_to_sum]) / weights[i_radial]
|
|
82
|
-
else:
|
|
83
|
-
histogram_1d[i_radial] = 0
|
|
84
|
-
return histogram_1d, radial_bin_edges
|
|
85
|
-
|
|
86
9
|
|
|
87
10
|
@u.quantity_input(rotation_angle_phi=u.rad, rotation_angle_theta=u.rad)
|
|
88
11
|
def rotate(x, y, rotation_around_z_axis, rotation_around_y_axis=0):
|
simtools/utils/names.py
CHANGED
|
@@ -189,13 +189,13 @@ def model_parameters(class_key_list=None):
|
|
|
189
189
|
dict
|
|
190
190
|
Model parameters definitions.
|
|
191
191
|
"""
|
|
192
|
-
_parameters = {}
|
|
193
192
|
if class_key_list is None:
|
|
194
193
|
return _load_model_parameters()
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
194
|
+
return {
|
|
195
|
+
key: value
|
|
196
|
+
for key, value in _load_model_parameters().items()
|
|
197
|
+
if value.get("instrument", {}).get("class", "") in class_key_list
|
|
198
|
+
}
|
|
199
199
|
|
|
200
200
|
|
|
201
201
|
def site_parameters():
|
simtools/utils/random.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Random numbers utilities."""
|
|
2
|
+
|
|
3
|
+
import secrets
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def seeds(n_seeds=1, min_seed=1, max_seed=2_000_000_000, fixed_seed=None):
|
|
9
|
+
"""
|
|
10
|
+
Generate independent random seeds.
|
|
11
|
+
|
|
12
|
+
Parameters
|
|
13
|
+
----------
|
|
14
|
+
n_seeds : int
|
|
15
|
+
Number of seeds to generate.
|
|
16
|
+
min_seed : int
|
|
17
|
+
Lower limit for the seed (inclusive).
|
|
18
|
+
max_seed : int
|
|
19
|
+
Upper limit for the seed (exclusive).
|
|
20
|
+
fixed_seed : int or None
|
|
21
|
+
If provided, use this fixed seed.
|
|
22
|
+
|
|
23
|
+
Returns
|
|
24
|
+
-------
|
|
25
|
+
int or list of int:
|
|
26
|
+
A single seed if n_seeds is 1, otherwise a list of seeds.
|
|
27
|
+
"""
|
|
28
|
+
entropy = fixed_seed if fixed_seed is not None else secrets.randbits(128)
|
|
29
|
+
ss = np.random.SeedSequence(entropy)
|
|
30
|
+
rng = np.random.default_rng(ss)
|
|
31
|
+
|
|
32
|
+
seed_list = rng.integers(low=min_seed, high=max_seed, size=n_seeds)
|
|
33
|
+
|
|
34
|
+
if n_seeds == 1:
|
|
35
|
+
return int(seed_list[0])
|
|
36
|
+
return [int(x) for x in seed_list]
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
"""Helper functions for legend handlers used for plotting."""
|
|
2
2
|
|
|
3
|
+
# pylint: disable=too-few-public-methods
|
|
4
|
+
|
|
3
5
|
import matplotlib.colors as mcolors
|
|
4
6
|
import matplotlib.patches as mpatches
|
|
5
7
|
import numpy as np
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Radii are relative to a reference radius (REFERENCE_RADIUS).
|
|
11
|
-
"""
|
|
9
|
+
# Define properties of different telescope types for visualization purposes.
|
|
10
|
+
# Radii are relative to a reference radius (REFERENCE_RADIUS).
|
|
12
11
|
TELESCOPE_CONFIG = {
|
|
13
12
|
"LST": {"color": "darkorange", "radius": 12.5, "shape": "circle", "filled": False},
|
|
14
13
|
"MST": {"color": "dodgerblue", "radius": 9.15, "shape": "circle", "filled": False},
|
|
@@ -51,7 +50,7 @@ def get_telescope_config(telescope_type):
|
|
|
51
50
|
config = TELESCOPE_CONFIG.get(telescope_type)
|
|
52
51
|
if not config and len(telescope_type) >= 3:
|
|
53
52
|
config = TELESCOPE_CONFIG.get(telescope_type[:3])
|
|
54
|
-
return config
|
|
53
|
+
return config.copy() if config else None
|
|
55
54
|
|
|
56
55
|
|
|
57
56
|
def calculate_center(handlebox, width_factor=3, height_factor=3):
|
|
@@ -272,6 +271,8 @@ class BaseLegendHandler:
|
|
|
272
271
|
x0, y0 = calculate_center(handlebox)
|
|
273
272
|
radius = handlebox.height
|
|
274
273
|
patch = self._create_hexagon(handlebox, x0, y0, radius)
|
|
274
|
+
else:
|
|
275
|
+
raise ValueError(f"Unknown shape: {shape}")
|
|
275
276
|
|
|
276
277
|
handlebox.add_artist(patch)
|
|
277
278
|
return patch
|
|
@@ -5,15 +5,18 @@ from collections import Counter
|
|
|
5
5
|
from typing import NamedTuple
|
|
6
6
|
|
|
7
7
|
import astropy.units as u
|
|
8
|
+
import matplotlib as mpl
|
|
8
9
|
import matplotlib.patches as mpatches
|
|
9
10
|
import matplotlib.pyplot as plt
|
|
10
11
|
import numpy as np
|
|
12
|
+
from adjustText import adjust_text
|
|
11
13
|
from astropy.table import Column
|
|
12
14
|
from matplotlib.collections import PatchCollection
|
|
13
15
|
|
|
14
16
|
from simtools.utils import geometry as transf
|
|
15
17
|
from simtools.utils import names
|
|
16
18
|
from simtools.visualization import legend_handlers as leg_h
|
|
19
|
+
from simtools.visualization import visualize
|
|
17
20
|
|
|
18
21
|
|
|
19
22
|
class PlotBounds(NamedTuple):
|
|
@@ -31,6 +34,61 @@ class PlotBounds(NamedTuple):
|
|
|
31
34
|
y_lim: tuple[float, float]
|
|
32
35
|
|
|
33
36
|
|
|
37
|
+
def plot_array_layouts(args_dict, output_path, layouts, background_layout=None):
|
|
38
|
+
"""
|
|
39
|
+
Plot multiple array layouts.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
args_dict : dict
|
|
44
|
+
Application arguments.
|
|
45
|
+
output_path : Path
|
|
46
|
+
Output path for figures.
|
|
47
|
+
layouts : dict
|
|
48
|
+
Dictionary of layout name to telescope table.
|
|
49
|
+
background_layout : Table or None
|
|
50
|
+
Optional background telescope table.
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
figs : dict
|
|
55
|
+
Dictionary of layout name to matplotlib figure object.
|
|
56
|
+
|
|
57
|
+
"""
|
|
58
|
+
mpl.use("Agg")
|
|
59
|
+
for layout in layouts:
|
|
60
|
+
fig_out = plot_array_layout(
|
|
61
|
+
telescopes=layout["array_elements"],
|
|
62
|
+
show_tel_label=args_dict["show_labels"],
|
|
63
|
+
axes_range=args_dict["axes_range"],
|
|
64
|
+
marker_scaling=args_dict["marker_scaling"],
|
|
65
|
+
background_telescopes=background_layout,
|
|
66
|
+
grayed_out_elements=args_dict["grayed_out_array_elements"],
|
|
67
|
+
highlighted_elements=args_dict["highlighted_array_elements"],
|
|
68
|
+
legend_location=args_dict["legend_location"],
|
|
69
|
+
bounds_mode=args_dict["bounds"],
|
|
70
|
+
padding=args_dict["padding"],
|
|
71
|
+
x_lim=tuple(args_dict["x_lim"]) if args_dict["x_lim"] else None,
|
|
72
|
+
y_lim=tuple(args_dict["y_lim"]) if args_dict["y_lim"] else None,
|
|
73
|
+
)
|
|
74
|
+
site_string = ""
|
|
75
|
+
if layout.get("site") is not None:
|
|
76
|
+
site_string = f"_{layout['site']}"
|
|
77
|
+
elif args_dict["site"] is not None:
|
|
78
|
+
site_string = f"_{args_dict['site']}"
|
|
79
|
+
coordinate_system_string = (
|
|
80
|
+
f"_{args_dict['coordinate_system']}"
|
|
81
|
+
if args_dict["coordinate_system"] not in layout["name"]
|
|
82
|
+
else ""
|
|
83
|
+
)
|
|
84
|
+
plot_file_name = args_dict["figure_name"] or (
|
|
85
|
+
f"array_layout_{layout['name']}{site_string}{coordinate_system_string}"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
visualize.save_figure(fig_out, output_path / plot_file_name, dpi=400)
|
|
89
|
+
plt.close()
|
|
90
|
+
|
|
91
|
+
|
|
34
92
|
def plot_array_layout(
|
|
35
93
|
telescopes,
|
|
36
94
|
show_tel_label=False,
|
|
@@ -89,7 +147,7 @@ def plot_array_layout(
|
|
|
89
147
|
filter_x = x_lim
|
|
90
148
|
filter_y = y_lim
|
|
91
149
|
|
|
92
|
-
patches, plot_range, highlighted_patches, bounds = get_patches(
|
|
150
|
+
patches, plot_range, highlighted_patches, bounds, text_objects = get_patches(
|
|
93
151
|
ax,
|
|
94
152
|
telescopes,
|
|
95
153
|
show_tel_label,
|
|
@@ -122,6 +180,17 @@ def plot_array_layout(
|
|
|
122
180
|
|
|
123
181
|
finalize_plot(ax, patches, "Easting [m]", "Northing [m]", x_lim, y_lim, highlighted_patches)
|
|
124
182
|
|
|
183
|
+
if text_objects:
|
|
184
|
+
adjust_text(
|
|
185
|
+
text_objects,
|
|
186
|
+
ax=ax,
|
|
187
|
+
arrowprops={"arrowstyle": "->", "color": "grey", "alpha": 0.8, "lw": 0.8, "ls": "--"},
|
|
188
|
+
expand=(2.0, 2.0),
|
|
189
|
+
prevent_crossings=True,
|
|
190
|
+
min_arrow_len=8,
|
|
191
|
+
ensure_inside_axes=True,
|
|
192
|
+
)
|
|
193
|
+
|
|
125
194
|
return fig
|
|
126
195
|
|
|
127
196
|
|
|
@@ -178,7 +247,7 @@ def _get_patches_for_background_telescopes(
|
|
|
178
247
|
if background_telescopes is None:
|
|
179
248
|
return plot_range, bounds
|
|
180
249
|
|
|
181
|
-
bg_patches, bg_range, _, bg_bounds = get_patches(
|
|
250
|
+
bg_patches, bg_range, _, bg_bounds, _ = get_patches(
|
|
182
251
|
ax,
|
|
183
252
|
background_telescopes,
|
|
184
253
|
False,
|
|
@@ -268,6 +337,8 @@ def get_patches(
|
|
|
268
337
|
List of highlighted telescope patches.
|
|
269
338
|
bounds : PlotBounds
|
|
270
339
|
Min/max for x and y in meters.
|
|
340
|
+
text_objects : list
|
|
341
|
+
List of text objects for labels.
|
|
271
342
|
"""
|
|
272
343
|
pos_x, pos_y = get_positions(telescopes)
|
|
273
344
|
tel_table, pos_x, pos_y = _apply_limits_filter(
|
|
@@ -277,7 +348,7 @@ def get_patches(
|
|
|
277
348
|
tel_table["pos_x_rotated"] = Column(pos_x)
|
|
278
349
|
tel_table["pos_y_rotated"] = Column(pos_y)
|
|
279
350
|
|
|
280
|
-
patches, radii, highlighted_patches = create_patches(
|
|
351
|
+
patches, radii, highlighted_patches, text_objects = create_patches(
|
|
281
352
|
tel_table, marker_scaling, show_tel_label, ax, grayed_out_elements, highlighted_elements
|
|
282
353
|
)
|
|
283
354
|
|
|
@@ -290,8 +361,8 @@ def get_patches(
|
|
|
290
361
|
if len(pos_x) == 0:
|
|
291
362
|
bounds = PlotBounds(x_lim=(0.0, 0.0), y_lim=(0.0, 0.0))
|
|
292
363
|
if axes_range:
|
|
293
|
-
return patches, axes_range, highlighted_patches, bounds
|
|
294
|
-
return patches, 0.0, highlighted_patches, bounds
|
|
364
|
+
return patches, axes_range, highlighted_patches, bounds, text_objects
|
|
365
|
+
return patches, 0.0, highlighted_patches, bounds, text_objects
|
|
295
366
|
|
|
296
367
|
x_min = float(np.nanmin(pos_x).to_value(u.m)) - r
|
|
297
368
|
x_max = float(np.nanmax(pos_x).to_value(u.m)) + r
|
|
@@ -300,13 +371,13 @@ def get_patches(
|
|
|
300
371
|
bounds = PlotBounds(x_lim=(x_min, x_max), y_lim=(y_min, y_max))
|
|
301
372
|
|
|
302
373
|
if axes_range:
|
|
303
|
-
return patches, axes_range, highlighted_patches, bounds
|
|
374
|
+
return patches, axes_range, highlighted_patches, bounds, text_objects
|
|
304
375
|
|
|
305
376
|
max_x = max(abs(x_min), abs(x_max))
|
|
306
377
|
max_y = max(abs(y_min), abs(y_max))
|
|
307
378
|
updated_axes_range = max(max_x, max_y) * 1.1
|
|
308
379
|
|
|
309
|
-
return patches, updated_axes_range, highlighted_patches, bounds
|
|
380
|
+
return patches, updated_axes_range, highlighted_patches, bounds, text_objects
|
|
310
381
|
|
|
311
382
|
|
|
312
383
|
@u.quantity_input(x=u.m, y=u.m, radius=u.m)
|
|
@@ -417,8 +488,10 @@ def create_patches(
|
|
|
417
488
|
Telescope radii.
|
|
418
489
|
highlighted_patches : list
|
|
419
490
|
List of highlighted telescope patches.
|
|
491
|
+
text_objects : list
|
|
492
|
+
List of text objects for labels.
|
|
420
493
|
"""
|
|
421
|
-
patches, radii, highlighted_patches = [], [], []
|
|
494
|
+
patches, radii, highlighted_patches, text_objects = [], [], [], []
|
|
422
495
|
fontsize, scale_factor = (4, 2) if len(telescopes) > 30 else (8, 1)
|
|
423
496
|
|
|
424
497
|
grayed_out_set = set(grayed_out_elements) if grayed_out_elements else set()
|
|
@@ -457,16 +530,18 @@ def create_patches(
|
|
|
457
530
|
highlighted_patches.append(highlight_patch)
|
|
458
531
|
|
|
459
532
|
if show_label:
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
533
|
+
text_objects.append(
|
|
534
|
+
ax.text(
|
|
535
|
+
tel["pos_x_rotated"].value,
|
|
536
|
+
tel["pos_y_rotated"].value + scale_factor * radius.value,
|
|
537
|
+
name,
|
|
538
|
+
ha="center",
|
|
539
|
+
va="center",
|
|
540
|
+
fontsize=fontsize * 0.8,
|
|
541
|
+
)
|
|
467
542
|
)
|
|
468
543
|
|
|
469
|
-
return patches, radii, highlighted_patches
|
|
544
|
+
return patches, radii, highlighted_patches, text_objects
|
|
470
545
|
|
|
471
546
|
|
|
472
547
|
def get_telescope_name(tel):
|