ModuleOpticalElement
24class OpticalElement: 25 """ 26 An optical element, to define the position and orientation of different optics in the 'lab-frame'. 27 28 Attributes 29 ---------- 30 type : An instance of a class of optic, i.e. a Mirror and Mask. 31 32 position : np.ndarray 33 Coordinate vector of the optical element’s center point in the lab frame. 34 What this center is, depends on the 'type', but it is generally the center of symmetry 35 of the Support of the optic. It is marked by the point 'P' in the drawings in the 36 documentation of the Mirror-classes for example. 37 38 normal : np.ndarray 39 Lab-frame vector pointing against the direction that would be considered 40 as normal incidence on the optical element. 41 42 majoraxis : np.ndarray 43 Lab-frame vector of another distinguished axis of non-rotationally symmetric optics, 44 like the major axes of toroidal/elliptical mirrors or the off-axis direction of 45 off-axis parabolas. This fixes the optical element’s rotation about 'normal'. 46 It is required to be perpendicular to 'normal', and is usually the x-axis in the 47 optic's proper coordinate frame. 48 49 What this 'majoraxis' is, e.g. for the different kinds of mirrors, is illustrated 50 in the documentation of the Mirror-classes. 51 52 For pure p or s polarization, the light incidence plane should be the 53 plane spanned by 'normal' and 'majoraxis', so that the incidence angle is varied 54 by rotating the optical element around the cross product 'normal' x 'majoraxis'. 55 56 57 Methods 58 ---------- 59 rotate_pitch_by(angle) 60 61 rotate_roll_by(angle) 62 63 rotate_yaw_by(angle) 64 65 rotate_random_by(angle) 66 67 shift_along_normal(distance) 68 69 shift_along_major(distance) 70 71 shift_along_cross(distance) 72 73 shift_along_random(distance) 74 75 """ 76 77 def __init__(self, Type, Position, Normal, MajorAxis): 78 """ 79 Parameters 80 ---------- 81 Type : Object of a Mirror or Mask-class 82 83 Position : np.ndarray 84 Coordinate vector of the optical element’s center point in the lab frame. 85 What this center is, depends on the 'type', but it is generally the center of symmetry 86 of the Support of the optic. It is marked by the point 'P' in the drawings in the 87 documentation of the Mirror-classes for example. 88 89 Normal : np.ndarray 90 Lab-frame vector pointing against the direction that would be considered 91 as normal incidence on the optical element. 92 93 MajorAxis : np.ndarray 94 Lab-frame vector of another distinguished axis, of non-rotationally symmetric elements, 95 like the major axes of toroidal/elliptical mirrors or the off-axis direction of off-axis 96 parabolas. It is required to be perpendicular to 'normal', and is usually the x-axis in 97 the optic's proper coordinate frame. 98 99 What this 'majoraxis' is for, e.g., the different kinds of mirrors, is illustrated 100 in the documentation of the Mirror-classes. 101 102 """ 103 self._type = Type 104 self.position = Position 105 self.normal = mgeo.Normalize(Normal) 106 self.majoraxis = mgeo.Normalize(MajorAxis) 107 108 # using property decorator 109 # a getter function 110 @property 111 def position(self): 112 return self._position 113 114 # a setter function 115 @position.setter 116 def position(self, NewPosition): 117 if type(NewPosition) == np.ndarray and len(NewPosition) == 3: 118 self._position = NewPosition 119 else: 120 raise TypeError("Position must be a 3D numpy.ndarray.") 121 122 @property 123 def normal(self): 124 return self._normal 125 126 @normal.setter 127 def normal(self, NewNormal): 128 if type(NewNormal) == np.ndarray and len(NewNormal) == 3 and np.linalg.norm(NewNormal) > 0: 129 try: 130 if abs(np.dot(mgeo.Normalize(NewNormal), self.majoraxis)) > 1e-12: 131 # if the new normal is not perpendicular to the majoraxis, then we rotate the major along with the rotation of the normal vector 132 self._majoraxis = mgeo.RotationAroundAxis( 133 np.cross(self.normal, NewNormal), 134 mgeo.AngleBetweenTwoVectors(self.normal, NewNormal), 135 self.majoraxis, 136 ) 137 except Exception: 138 pass # this is for the initialization when the majoraxis isn't defined yet and the test above fails 139 140 self._normal = mgeo.Normalize(NewNormal) 141 else: 142 raise TypeError("Normal must be a 3D numpy.ndarray with finite length.") 143 144 @property 145 def majoraxis(self): 146 return self._majoraxis 147 148 @majoraxis.setter 149 def majoraxis(self, NewMajorAxis): 150 if type(NewMajorAxis) == np.ndarray and len(NewMajorAxis) == 3 and np.linalg.norm(NewMajorAxis) > 0: 151 if abs(np.dot(self.normal, mgeo.Normalize(NewMajorAxis))) > 1e-12: 152 raise ValueError("The normal and major axis of optical elements need to be orthogonal!") 153 self._majoraxis = mgeo.Normalize(NewMajorAxis) 154 else: 155 raise TypeError("MajorAxis must be a 3D numpy.ndarray with finite length.") 156 157 # make the type property private and providing only a getter method, so it can't be modified after the class instance has been created 158 @property 159 def type(self): 160 return self._type 161 162 def __hash__(self): 163 position_tuple = tuple(self.position.reshape(1, -1)[0]) 164 normal_tuple = tuple(self.normal.reshape(1, -1)[0]) 165 majoraxis_tuple = tuple(self.majoraxis.reshape(1, -1)[0]) 166 return hash(position_tuple + normal_tuple + majoraxis_tuple) + hash(self.type) 167 168 # %% methods to (mis-)align the OE 169 170 def rotate_pitch_by(self, angle): 171 """ 172 Pitch rotation, i.e. rotates the optical element about the axis ('normal' x 'majraxis'), by the 173 given angle. 174 If the plane spanned by 'normal' and 'majoraxis' is the incidence plane (normally the case 175 in a "clean alignment" situation for pure p or s polarization), then this is simply a modificaiton 176 of the incidence angle by "angle". But in general, if the optical element has some odd orientation, 177 there is not a direct correspondence. 178 179 Parameters 180 ---------- 181 angle : float 182 Rotation angle in *degrees*. 183 """ 184 rotation_axis = np.cross(self.normal, self.majoraxis) 185 self.normal = mgeo.RotationAroundAxis(rotation_axis, np.deg2rad(angle), self.normal) 186 # the normal.setter function should take care of the majoraxis remaining perpendicular to the normal. 187 188 def rotate_roll_by(self, angle): 189 """ 190 Roll rotation, i.e. rotates the optical element about its 'majoraxis' by the given angle. 191 192 Parameters 193 ---------- 194 angle : float 195 Rotation angle in *degrees*. 196 """ 197 198 self.normal = mgeo.RotationAroundAxis(self.majoraxis, np.deg2rad(angle), self.normal) 199 200 def rotate_yaw_by(self, angle): 201 """ 202 Yaw rotation, i.e. rotates the optical element about its 'normal' by the given angle. 203 204 Parameters 205 ---------- 206 angle : float 207 Rotation angle in *degrees*. 208 """ 209 self.majoraxis = mgeo.RotationAroundAxis(self.normal, np.deg2rad(angle), self.majoraxis) 210 211 def rotate_random_by(self, angle): 212 """ 213 Rotates the optical element about a randomly oriented axis by the given angle. 214 215 Parameters 216 ---------- 217 angle : float 218 Rotation angle in *degrees*. 219 """ 220 221 self.normal = mgeo.RotationAroundAxis(np.random.random(3), np.deg2rad(angle), self.normal) 222 223 def shift_along_normal(self, distance): 224 """ 225 Shifts the optical element along its 'normal' by the given distance. 226 227 Parameters 228 ---------- 229 distance : float 230 Shift distance in mm. 231 """ 232 self.position += distance * self.normal 233 234 def shift_along_major(self, distance): 235 """ 236 Shifts the optical element along its 'majoraxis' by the given distance. 237 238 Parameters 239 ---------- 240 distance : float 241 Shift distance in mm. 242 """ 243 self.position += distance * self.majoraxis 244 245 def shift_along_cross(self, distance): 246 """ 247 Shifts the optical element along the axis 'normal'x'majoraxis' 248 (typically normal to the light incidence plane) by the given distance. 249 250 Parameters 251 ---------- 252 distance : float 253 Shift distance in mm. 254 """ 255 self.position += distance * mgeo.Normalize(np.cross(self.normal, self.majoraxis)) 256 257 def shift_along_random(self, distance): 258 """ 259 Shifts the optical element along a random direction by the given distance. 260 261 Parameters 262 ---------- 263 distance : float 264 Shift distance in mm. 265 """ 266 self.position += distance * mgeo.Normalize(np.random.random(3))
An optical element, to define the position and orientation of different optics in the 'lab-frame'.
Attributes
type : An instance of a class of optic, i.e. a Mirror and Mask.
position : np.ndarray
Coordinate vector of the optical element’s center point in the lab frame.
What this center is, depends on the 'type', but it is generally the center of symmetry
of the Support of the optic. It is marked by the point 'P' in the drawings in the
documentation of the Mirror-classes for example.
normal : np.ndarray
Lab-frame vector pointing against the direction that would be considered
as normal incidence on the optical element.
majoraxis : np.ndarray
Lab-frame vector of another distinguished axis of non-rotationally symmetric optics,
like the major axes of toroidal/elliptical mirrors or the off-axis direction of
off-axis parabolas. This fixes the optical element’s rotation about 'normal'.
It is required to be perpendicular to 'normal', and is usually the x-axis in the
optic's proper coordinate frame.
What this 'majoraxis' is, e.g. for the different kinds of mirrors, is illustrated
in the documentation of the Mirror-classes.
For pure p or s polarization, the light incidence plane should be the
plane spanned by 'normal' and 'majoraxis', so that the incidence angle is varied
by rotating the optical element around the cross product 'normal' x 'majoraxis'.
Methods
rotate_pitch_by(angle)
rotate_roll_by(angle)
rotate_yaw_by(angle)
rotate_random_by(angle)
shift_along_normal(distance)
shift_along_major(distance)
shift_along_cross(distance)
shift_along_random(distance)
77 def __init__(self, Type, Position, Normal, MajorAxis): 78 """ 79 Parameters 80 ---------- 81 Type : Object of a Mirror or Mask-class 82 83 Position : np.ndarray 84 Coordinate vector of the optical element’s center point in the lab frame. 85 What this center is, depends on the 'type', but it is generally the center of symmetry 86 of the Support of the optic. It is marked by the point 'P' in the drawings in the 87 documentation of the Mirror-classes for example. 88 89 Normal : np.ndarray 90 Lab-frame vector pointing against the direction that would be considered 91 as normal incidence on the optical element. 92 93 MajorAxis : np.ndarray 94 Lab-frame vector of another distinguished axis, of non-rotationally symmetric elements, 95 like the major axes of toroidal/elliptical mirrors or the off-axis direction of off-axis 96 parabolas. It is required to be perpendicular to 'normal', and is usually the x-axis in 97 the optic's proper coordinate frame. 98 99 What this 'majoraxis' is for, e.g., the different kinds of mirrors, is illustrated 100 in the documentation of the Mirror-classes. 101 102 """ 103 self._type = Type 104 self.position = Position 105 self.normal = mgeo.Normalize(Normal) 106 self.majoraxis = mgeo.Normalize(MajorAxis)
Parameters
Type : Object of a Mirror or Mask-class
Position : np.ndarray
Coordinate vector of the optical element’s center point in the lab frame.
What this center is, depends on the 'type', but it is generally the center of symmetry
of the Support of the optic. It is marked by the point 'P' in the drawings in the
documentation of the Mirror-classes for example.
Normal : np.ndarray
Lab-frame vector pointing against the direction that would be considered
as normal incidence on the optical element.
MajorAxis : np.ndarray
Lab-frame vector of another distinguished axis, of non-rotationally symmetric elements,
like the major axes of toroidal/elliptical mirrors or the off-axis direction of off-axis
parabolas. It is required to be perpendicular to 'normal', and is usually the x-axis in
the optic's proper coordinate frame.
What this 'majoraxis' is for, e.g., the different kinds of mirrors, is illustrated
in the documentation of the Mirror-classes.
170 def rotate_pitch_by(self, angle): 171 """ 172 Pitch rotation, i.e. rotates the optical element about the axis ('normal' x 'majraxis'), by the 173 given angle. 174 If the plane spanned by 'normal' and 'majoraxis' is the incidence plane (normally the case 175 in a "clean alignment" situation for pure p or s polarization), then this is simply a modificaiton 176 of the incidence angle by "angle". But in general, if the optical element has some odd orientation, 177 there is not a direct correspondence. 178 179 Parameters 180 ---------- 181 angle : float 182 Rotation angle in *degrees*. 183 """ 184 rotation_axis = np.cross(self.normal, self.majoraxis) 185 self.normal = mgeo.RotationAroundAxis(rotation_axis, np.deg2rad(angle), self.normal) 186 # the normal.setter function should take care of the majoraxis remaining perpendicular to the normal.
Pitch rotation, i.e. rotates the optical element about the axis ('normal' x 'majraxis'), by the given angle. If the plane spanned by 'normal' and 'majoraxis' is the incidence plane (normally the case in a "clean alignment" situation for pure p or s polarization), then this is simply a modificaiton of the incidence angle by "angle". But in general, if the optical element has some odd orientation, there is not a direct correspondence.
Parameters
angle : float
Rotation angle in *degrees*.
188 def rotate_roll_by(self, angle): 189 """ 190 Roll rotation, i.e. rotates the optical element about its 'majoraxis' by the given angle. 191 192 Parameters 193 ---------- 194 angle : float 195 Rotation angle in *degrees*. 196 """ 197 198 self.normal = mgeo.RotationAroundAxis(self.majoraxis, np.deg2rad(angle), self.normal)
Roll rotation, i.e. rotates the optical element about its 'majoraxis' by the given angle.
Parameters
angle : float
Rotation angle in *degrees*.
200 def rotate_yaw_by(self, angle): 201 """ 202 Yaw rotation, i.e. rotates the optical element about its 'normal' by the given angle. 203 204 Parameters 205 ---------- 206 angle : float 207 Rotation angle in *degrees*. 208 """ 209 self.majoraxis = mgeo.RotationAroundAxis(self.normal, np.deg2rad(angle), self.majoraxis)
Yaw rotation, i.e. rotates the optical element about its 'normal' by the given angle.
Parameters
angle : float
Rotation angle in *degrees*.
211 def rotate_random_by(self, angle): 212 """ 213 Rotates the optical element about a randomly oriented axis by the given angle. 214 215 Parameters 216 ---------- 217 angle : float 218 Rotation angle in *degrees*. 219 """ 220 221 self.normal = mgeo.RotationAroundAxis(np.random.random(3), np.deg2rad(angle), self.normal)
Rotates the optical element about a randomly oriented axis by the given angle.
Parameters
angle : float
Rotation angle in *degrees*.
223 def shift_along_normal(self, distance): 224 """ 225 Shifts the optical element along its 'normal' by the given distance. 226 227 Parameters 228 ---------- 229 distance : float 230 Shift distance in mm. 231 """ 232 self.position += distance * self.normal
Shifts the optical element along its 'normal' by the given distance.
Parameters
distance : float
Shift distance in mm.
234 def shift_along_major(self, distance): 235 """ 236 Shifts the optical element along its 'majoraxis' by the given distance. 237 238 Parameters 239 ---------- 240 distance : float 241 Shift distance in mm. 242 """ 243 self.position += distance * self.majoraxis
Shifts the optical element along its 'majoraxis' by the given distance.
Parameters
distance : float
Shift distance in mm.
245 def shift_along_cross(self, distance): 246 """ 247 Shifts the optical element along the axis 'normal'x'majoraxis' 248 (typically normal to the light incidence plane) by the given distance. 249 250 Parameters 251 ---------- 252 distance : float 253 Shift distance in mm. 254 """ 255 self.position += distance * mgeo.Normalize(np.cross(self.normal, self.majoraxis))
Shifts the optical element along the axis 'normal'x'majoraxis' (typically normal to the light incidence plane) by the given distance.
Parameters
distance : float
Shift distance in mm.
257 def shift_along_random(self, distance): 258 """ 259 Shifts the optical element along a random direction by the given distance. 260 261 Parameters 262 ---------- 263 distance : float 264 Shift distance in mm. 265 """ 266 self.position += distance * mgeo.Normalize(np.random.random(3))
Shifts the optical element along a random direction by the given distance.
Parameters
distance : float
Shift distance in mm.