Coverage for rta_reconstruction/utils/optics.py: 80%
39 statements
« prev ^ index » next coverage.py v7.6.7, created at 2024-11-16 09:59 +0000
« prev ^ index » next coverage.py v7.6.7, created at 2024-11-16 09:59 +0000
1from enum import Enum, StrEnum, unique
3import astropy.units as u
4import numpy as np
7@unique
8class SizeType(StrEnum):
9 """
10 Enumeration of different telescope sizes (LST, MST, SST)
11 """
13 #: Unkown
14 UNKNOWN = "UNKNOWN"
15 #: A telescope with a mirror diameter larger than 16m
16 LST = "LST"
17 #: A telescope with a mirror diameter larger than 8m
18 MST = "MST"
19 #: Telescopes with a mirror diameter smaller than 8m
20 SST = "SST"
23@unique
24class ReflectorShape(Enum):
25 """
26 Enumeration of the different reflector shapes
27 """
29 #: Unkown
30 UNKNOWN = "UNKNOWN"
31 #: A telescope with a parabolic dish
32 PARABOLIC = "PARABOLIC"
33 #: A telescope with a Davies--Cotton dish
34 DAVIES_COTTON = "DAVIES_COTTON"
35 #: A telescope with a hybrid between parabolic and Davies--Cotton dish
36 HYBRID = "HYBRID"
37 #: A dual mirror Schwarzschild-Couder reflector
38 SCHWARZSCHILD_COUDER = "SCHWARZSCHILD_COUDER"
41class OpticsDescription:
42 """
43 Describes the optics of a Cherenkov Telescope mirror
45 The string representation of an `OpticsDescription` will be a combination
46 of the telescope-type and sub-type as follows: "type-subtype". You can
47 also get each individually.
49 Parameters
50 ----------
51 name : str
52 Name of this optical system
53 n_mirrors : int
54 Number of mirrors, i. e. 2 for Schwarzschild-Couder else 1
55 equivalent_focal_length : astropy.units.Quantity[length]
56 Equivalent focal-length of telescope, independent of which type of
57 optics (as in the Monte-Carlo). This is the nominal focal length
58 for single mirror telescopes and the equivalent focal length for dual
59 mirror telescopes.
60 effective_focal_length : astropy.units.Quantity[length]
61 The effective_focal_length is the focal length estimated from
62 ray tracing to correct for coma aberration. It is thus not automatically
63 available for all simulations, but only if it was set beforehand
64 in the simtel configuration. This is the focal length that should be
65 used for transforming from camera frame to telescope frame for all
66 reconstruction tasks to correct for the mean aberration.
67 mirror_area : astropy.units.Quantity[area]
68 total reflective surface area of the optical system (in m^2)
69 n_mirror_tiles : int
70 number of mirror facets
72 Raises
73 ------
74 ValueError:
75 if tel_type or mirror_type are not one of the accepted values
76 TypeError, astropy.units.UnitsError:
77 if the units of one of the inputs are missing or incompatible
78 """
80 CURRENT_TAB_VERSION = "4.0"
81 COMPATIBLE_VERSIONS = {"4.0"}
83 __slots__ = (
84 "name",
85 "size_type",
86 "effective_focal_length",
87 "equivalent_focal_length",
88 "mirror_area",
89 "n_mirrors",
90 "n_mirror_tiles",
91 "reflector_shape",
92 )
94 @u.quantity_input(
95 mirror_area=u.m**2,
96 equivalent_focal_length=u.m,
97 effective_focal_length=u.m,
98 )
99 def __init__(
100 self,
101 name,
102 size_type,
103 n_mirrors,
104 equivalent_focal_length,
105 effective_focal_length,
106 mirror_area,
107 n_mirror_tiles,
108 reflector_shape,
109 ):
110 self.name = name
111 self.size_type = SizeType(size_type)
112 self.reflector_shape = ReflectorShape(reflector_shape)
113 self.equivalent_focal_length = equivalent_focal_length.to(u.m)
114 self.effective_focal_length = effective_focal_length.to(u.m)
115 self.mirror_area = mirror_area
116 self.n_mirrors = n_mirrors
117 self.n_mirror_tiles = n_mirror_tiles
119 def __hash__(self):
120 """Make this hashable, so it can be used as dict keys or in sets"""
121 # From python >= 3.10, hash of nan is random, we want a fixed hash also for
122 # unknown effective focal length:
123 if np.isnan(self.effective_focal_length.value):
124 effective_focal_length = -1
125 else:
126 effective_focal_length = self.effective_focal_length.to_value(u.m)
128 return hash(
129 (
130 round(self.equivalent_focal_length.to_value(u.m), 4),
131 round(effective_focal_length, 4),
132 round(self.mirror_area.to_value(u.m**2)),
133 self.size_type.value,
134 self.reflector_shape.value,
135 self.n_mirrors,
136 self.n_mirror_tiles,
137 )
138 )
140 def __eq__(self, other):
141 """For eq, we just compare equal hash"""
142 return hash(self) == hash(other)
144 def __str__(self):
145 return self.name