Skip to content

Diagnostics

diagnostics

BeamDiagnostics

Mixin providing measurement/diagnostic methods for Beam: power, intensity/phase profiles, centroid and width statistics, angular sections, normalization and more.

Power

Power(pol_index=None) -> float

Get the total optical Power via numerical integration of the intensity profile (trapezoidal-like Riemann sum with the grid's cell area)

Parameters:

Name Type Description Default
pol_index

Polarization component into which the resulting power is measured. Default is power of all field components.

None

Returns:

Type Description
float
Source code in structured_optics\diagnostics.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def Power(self, pol_index=None) -> float:
    """Get the total optical Power via numerical integration of the intensity profile 
    (trapezoidal-like Riemann sum with the grid's cell area)

    Parameters
    ----------
    pol_index: int, optional
        Polarization component into which the resulting power is measured. Default is power of 
        all field components.

    Returns
    -------
    float
    """
    return np.sum(self.int_profile(pol_index))*(4*self.nix/self.Dx)*(self.niy/self.Dy)

zr

zr() -> float

Compute the Rayleigh range of the beam from its waist and lamb.

Returns:

Type Description
float

Rayleigh range, zr = piwaist*2/lamb.

Source code in structured_optics\diagnostics.py
29
30
31
32
33
34
35
36
37
38
def zr(self) -> float:
    """
    Compute the Rayleigh range of the beam from its `waist` and `lamb`.

    Returns
    -------
    float
        Rayleigh range, zr = pi*waist**2/lamb.
    """
    return np.pi*self.waist**2/self.lamb

k

k() -> float

Compute k vector magnitude in vacum.

Returns:

Type Description
float

k vector magniture in vaccum

Source code in structured_optics\diagnostics.py
40
41
42
43
44
45
46
47
48
def k(self) -> float:
    """
    Compute k vector magnitude in vacum.

    Returns
    -------
    float
        k vector magniture in vaccum"""
    return 2*np.pi/self.lamb

int_profile

int_profile(pol_index=None) -> np.ndarray

Get intensity profile.

pol_index=None -> total intensity pol_index=0 -> Ex intensity pol_index=1 -> Ey intensity pol_index=2 -> Ez intensity

Parameters:

Name Type Description Default
pol_index

Polarization component into which the resulting intensity profile is measured. Default is sum of all intensity components.

None
Return

ndarray Array with intensity profile (x,y).

Source code in structured_optics\diagnostics.py
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
def int_profile(self, pol_index=None) -> np.ndarray:
    """
    Get intensity profile.

    pol_index=None -> total intensity
    pol_index=0    -> Ex intensity
    pol_index=1    -> Ey intensity
    pol_index=2    -> Ez intensity

    Parameters
    ----------
    pol_index: int, optional
        Polarization component into which the resulting intensity profile is measured. Default is sum of 
        all intensity components.

    Return
    ------
    ndarray
        Array with intensity profile (x,y).
    """
    if pol_index is None:
        return np.sum(np.abs(self.field)**2, axis=0)
    return np.abs(self.field[pol_index])**2

phase

phase(pol_index=None, twopi=False) -> np.ndarray

Parameters:

Name Type Description Default
pol_index int or None

None returns phase of all components; 0/1/2 returns the phase of Ex/Ey/Ez respectively.

None
twopi bool

If True, wrap phase into [0, 2*pi) instead of the default (-pi, pi].

False

Returns:

Type Description
ndarray

Phase profile, shape (Dy, Dx) if pol_index is given or pol==1, otherwise shape (pol, Dy, Dx).

Source code in structured_optics\diagnostics.py
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
def phase(self, pol_index=None, twopi=False) -> np.ndarray:
    """
    Parameters
    ----------
    pol_index : int or None, optional
        None returns phase of all components; 0/1/2 returns the phase of
        Ex/Ey/Ez respectively.
    twopi : bool, optional
        If True, wrap phase into [0, 2*pi) instead of the default (-pi, pi].

    Returns
    -------
    ndarray
        Phase profile, shape (Dy, Dx) if pol_index is given or pol==1,
        otherwise shape (pol, Dy, Dx).
    """
    if pol_index is None:
        field = self.field
    else:
        field = self.field[pol_index]
    p = np.angle(field)
    if twopi:
        p = np.mod(p, 2*np.pi)
    if self.pol == 1:
        return p[0]
    return p

center_mass

center_mass(pol_index=None) -> tuple

Compute the intensity-weighted center of mass of the field in physical x and y coordinates.

Parameters

pol_index : int, optional Polarization component to use; None uses total intensity.

Returns

tuple (x_cm, y_cm) center-of-mass coordinates in physical units.

Source code in structured_optics\diagnostics.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
def center_mass(self, pol_index=None) -> tuple: 
    """ 
    Compute the intensity-weighted center of mass of the field in physical x and y coordinates. 

    Parameters 
    ---------- 
    pol_index : int, optional 
        Polarization component to use; None uses total intensity. 

    Returns 
    ------- 
    tuple (x_cm, y_cm) 
        center-of-mass coordinates in physical units. """ 
    I = self.int_profile(pol_index) 

    x = np.asarray(self.x) 
    y = np.asarray(self.y) 
    if x.ndim == 2: 
        x = x[0, :] if x.shape[0] == 1 else x[0, :] 
    if y.ndim == 2: 
        y = y[:, 0] if y.shape[1] == 1 else y[:, 0] 
    # Total intensity 
    norm = np.sum(I) 

    if norm == 0: 
        raise ValueError("Cannot calculate center of mass of zero intensity.") 

    # Intensity marginalized along each direction 
    Ix = np.sum(I, axis=0) 
    Iy = np.sum(I, axis=1) 

    # Physical center of mass 
    x_cm = np.sum(x * Ix) / norm 
    y_cm = np.sum(y * Iy) / norm 

    return x_cm, y_cm

std

std(pol_index=None)

Calculate the intensity-weighted spatial standard deviation along x and y.

Parameters

pol_index : int, optional Polarization component to use; None uses total intensity.

Returns:

Type Description
sigma_x, sigma_y : float

Intensity-weighted spatial standard deviations.

Source code in structured_optics\diagnostics.py
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
def std(self, pol_index=None): 
    """
    Calculate the intensity-weighted spatial standard deviation
    along x and y.

    Parameters 
    ---------- 
    pol_index : int, optional 
        Polarization component to use; None uses total intensity. 

    Returns
    -------
    sigma_x, sigma_y : float
        Intensity-weighted spatial standard deviations.
    """
    I = self.int_profile(pol_index) 
    x = np.asarray(self.x) 
    y = np.asarray(self.y) 
    x = x[0, :] if x.ndim == 2 else x 
    y = y[:, 0] if y.ndim == 2 else y 
    norm = np.sum(I) 
    Ix = np.sum(I, axis=0) 
    Iy = np.sum(I, axis=1) 
    x_cm, y_cm = self.center_mass(pol_index) 
    var_x = np.sum(Ix * (x - x_cm)**2) / norm 
    var_y = np.sum(Iy * (y - y_cm)**2) / norm 
    return np.sqrt(var_x), np.sqrt(var_y)

radial_std

radial_std(pol_index=None) -> float

Calculate the intensity-weighted radial standard deviation of the field about its center of mass.

Parameters:

Name Type Description Default
pol_index int

Polarization component to use; None uses total intensity.

None

Returns:

Type Description
float

Intensity-weighted radial standard deviation.

Source code in structured_optics\diagnostics.py
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
def radial_std(self, pol_index=None) -> float:
    """
    Calculate the intensity-weighted radial standard deviation of the field
    about its center of mass.

    Parameters
    ----------
    pol_index : int, optional
        Polarization component to use; None uses total intensity.

    Returns
    -------
    float
        Intensity-weighted radial standard deviation.
    """
    sx, sy = self.std(pol_index)

    return np.sqrt(sx**2 + sy**2)

section

section(ang_min: float, ang_max: float, pol_index: int = 0) -> np.ndarray

Parameters:

Name Type Description Default
ang_min float

Minimum angle (radians) defining the angular wedge.

required
ang_max float

Maximum angle (radians) defining the angular wedge.

required
pol_index int

Polarization component to extract the section from.

0

Returns:

Type Description
ndarray

Complex field values restricted to the angular wedge [ang_min, ang_max].

Source code in structured_optics\diagnostics.py
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
def section(self, ang_min:float, ang_max:float, pol_index:int=0) -> np.ndarray:
    """
    Parameters
    ----------
    ang_min : float
        Minimum angle (radians) defining the angular wedge.
    ang_max : float
        Maximum angle (radians) defining the angular wedge.
    pol_index : int, optional
        Polarization component to extract the section from.

    Returns
    -------
    ndarray
        Complex field values restricted to the angular wedge [ang_min, ang_max].
    """
    return get_section(self, ang_min, ang_max, pol_index = pol_index)

int_section

int_section(ang_min: float, ang_max: float, pol_index: int = 0) -> np.ndarray

Parameters:

Name Type Description Default
ang_min float

Minimum angle (radians) defining the angular wedge.

required
ang_max float

Maximum angle (radians) defining the angular wedge.

required
pol_index int

Polarization component to extract the section from.

0

Returns:

Type Description
ndarray

Intensity |field|^2 within the angular wedge [ang_min, ang_max].

Source code in structured_optics\diagnostics.py
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
def int_section(self, ang_min:float, ang_max:float, pol_index:int=0)-> np.ndarray:
    """
    Parameters
    ----------
    ang_min : float
        Minimum angle (radians) defining the angular wedge.
    ang_max : float
        Maximum angle (radians) defining the angular wedge.
    pol_index : int, optional
        Polarization component to extract the section from.

    Returns
    -------
    ndarray
        Intensity |field|^2 within the angular wedge [ang_min, ang_max].
    """
    return np.abs(self.section(ang_min, ang_max, pol_index = pol_index))**2

Power_section

Power_section(ang_min: float, ang_max: float, pol_index: int = 0) -> float

Parameters:

Name Type Description Default
ang_min float

Minimum angle (radians) defining the angular wedge.

required
ang_max float

Maximum angle (radians) defining the angular wedge.

required
pol_index int

Polarization component to compute power for.

0

Returns:

Type Description
float

Optical power contained within the angular wedge [ang_min, ang_max].

Source code in structured_optics\diagnostics.py
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
def Power_section(self, ang_min:float, ang_max:float, pol_index:int=0)-> float:
    """
    Parameters
    ----------
    ang_min : float
        Minimum angle (radians) defining the angular wedge.
    ang_max : float
        Maximum angle (radians) defining the angular wedge.
    pol_index : int, optional
        Polarization component to compute power for.

    Returns
    -------
    float
        Optical power contained within the angular wedge [ang_min, ang_max].
    """
    return np.sum(np.abs(self.section(ang_min, ang_max, pol_index = pol_index))**2*(4*self.nix/self.Dx)*(self.niy/self.Dy))

norm_beam

norm_beam() -> object

Returns:

Type Description
Beam

self, with field rescaled in place so that self.Power() == 1.

Source code in structured_optics\diagnostics.py
241
242
243
244
245
246
247
248
249
def norm_beam(self)-> object:                                       
    """
    Returns
    -------
    Beam
        self, with field rescaled in place so that self.Power() == 1.
    """
    self.field = self.field/np.sqrt(self.Power())
    return self

Max_int1

Max_int1() -> object

Returns:

Type Description
Beam

self, with field rescaled in place so that the peak intensity equals 1.

Source code in structured_optics\diagnostics.py
251
252
253
254
255
256
257
258
259
def Max_int1(self)-> object:                                         
    """
    Returns
    -------
    Beam
        self, with field rescaled in place so that the peak intensity equals 1.
    """
    self.field = self.field/np.sqrt(np.max(self.int_profile()))
    return self