ModuleOpticalElement

class OpticalElement:
 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)
OpticalElement(Type, Position, Normal, MajorAxis)
 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.
def rotate_pitch_by(self, angle):
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*.
def rotate_roll_by(self, angle):
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*.
def rotate_yaw_by(self, angle):
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*.
def rotate_random_by(self, angle):
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*.
def shift_along_normal(self, distance):
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.
def shift_along_major(self, distance):
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.
def shift_along_cross(self, distance):
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.
def shift_along_random(self, distance):
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.