Skip to content

Tools

tools

overlap

overlap(first_beam: object, second_beam: object) -> complex

Compute the (complex) field overlap integral between two beams.

Only gives a physically meaningful result if both beams share the same grid, i.e. the same nix/niy (half-window size) and the same Dx/Dy (sample count).

Parameters:

Name Type Description Default
first_beam object

First Beam instance.

required
second_beam object

Second Beam instance.

required

Returns:

Type Description
complex

The normalized overlap integral sum(E1 * conj(E2)) * dx * dy / sqrt(P1 * P2), where dx = 2*nix/Dx, dy = 2*niy/Dy, and P1, P2 are each beam's total power.

Source code in structured_optics\tools.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def overlap(first_beam:object, second_beam:object)->complex:
    """
    Compute the (complex) field overlap integral between two beams.

    Only gives a physically meaningful result if both beams share the
    same grid, i.e. the same `nix`/`niy` (half-window size) and the
    same `Dx`/`Dy` (sample count).

    Parameters
    ----------
    first_beam : object
        First Beam instance.
    second_beam : object
        Second Beam instance.

    Returns
    -------
    complex
        The normalized overlap integral
        ``sum(E1 * conj(E2)) * dx * dy / sqrt(P1 * P2)``, where
        `dx = 2*nix/Dx`, `dy = 2*niy/Dy`, and `P1`, `P2` are each
        beam's total power.
    """
    # calculate overlap between two beams, only properly works if ni and D of beams are equal.
    return np.sum(first_beam.field*np.conjugate(second_beam.field))*4*(first_beam.nix/first_beam.Dx) \
        *(first_beam.niy/first_beam.Dy)/np.sqrt(first_beam.Power()*second_beam.Power())

int_overlap

int_overlap(first_beam: object, second_beam: object) -> float

Compute the (real-valued, incoherent) intensity overlap between two beams.

Unlike overlap, this compares intensity profiles rather than complex fields, so it discards phase information and is insensitive to a relative phase between the two beams. Only gives a physically meaningful result if both beams share the same grid, i.e. the same nix/niy and Dx/Dy.

Parameters:

Name Type Description Default
first_beam object

First Beam instance.

required
second_beam object

Second Beam instance.

required

Returns:

Type Description
float

The normalized intensity overlap sum(I1 * I2) * dx * dy / (P1 * P2), where dx = 2*nix/Dx, dy = 2*niy/Dy, and P1, P2 are each beam's total power.

Source code in structured_optics\tools.py
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
def int_overlap(first_beam:object, second_beam:object)->float:
    """
    Compute the (real-valued, incoherent) intensity overlap between two
    beams.

    Unlike `overlap`, this compares intensity profiles rather than
    complex fields, so it discards phase information and is insensitive
    to a relative phase between the two beams. Only gives a physically
    meaningful result if both beams share the same grid, i.e. the same
    `nix`/`niy` and `Dx`/`Dy`.

    Parameters
    ----------
    first_beam : object
        First Beam instance.
    second_beam : object
        Second Beam instance.

    Returns
    -------
    float
        The normalized intensity overlap
        ``sum(I1 * I2) * dx * dy / (P1 * P2)``, where `dx = 2*nix/Dx`,
        `dy = 2*niy/Dy`, and `P1`, `P2` are each beam's total power.
    """
    return np.sum(first_beam.int_profile()*second_beam.int_profile())*4*(first_beam.nix/first_beam.Dx) \
        *(first_beam.niy/first_beam.Dy)/(first_beam.Power()*second_beam.Power())

hg_proj

hg_proj(Beam, N)

Project Beam onto the Hermite-Gaussian (HG) basis, up to order N in each index.

Parameters:

Name Type Description Default
Beam object

Beam instance to decompose. Not modified.

required
N int

Maximum HG index (inclusive) along both n and m; the basis used has (N+1) x (N+1) modes.

required

Returns:

Name Type Description
n, m : np.ndarray

Meshgrids (each of shape (N+1, N+1)) of the HG mode indices.

overlaps ndarray

Complex array of shape (N+1, N+1) where overlaps[n, m] is overlap(Beam, HG_{n,m}), i.e. the complex overlap of Beam with the HG mode of indices (n, m).

Source code in structured_optics\tools.py
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
def hg_proj(Beam,N):
    """
    Project `Beam` onto the Hermite-Gaussian (HG) basis, up to order N
    in each index.

    Parameters
    ----------
    Beam : object
        Beam instance to decompose. Not modified.
    N : int
        Maximum HG index (inclusive) along both `n` and `m`; the basis
        used has (N+1) x (N+1) modes.

    Returns
    -------
    n, m : np.ndarray
        Meshgrids (each of shape (N+1, N+1)) of the HG mode indices.
    overlaps : np.ndarray
        Complex array of shape (N+1, N+1) where `overlaps[n, m]` is
        `overlap(Beam, HG_{n,m})`, i.e. the complex overlap of `Beam`
        with the HG mode of indices (n, m).
    """
    overlaps = np.zeros((N+1, N+1), dtype='complex')
    auxiliary_beam  = Beam.copy_clean()
    for n in range(N+1):
        for m in range(N+1):
            auxiliary_beam.hg(n,m)
            overlaps[n,m] = overlap(Beam, auxiliary_beam)
    n, m =  np.meshgrid(np.arange(0, N+1, 1), np.arange(0, N+1, 1))
    return n, m, overlaps

lg_proj

lg_proj(Beam, N)

Project Beam onto the Laguerre-Gaussian (LG) basis, with azimuthal index l ranging over -N..N and radial index p ranging over 0..floor(N/2).

Parameters:

Name Type Description Default
Beam object

Beam instance to decompose. Not modified.

required
N int

Controls the range of azimuthal indices (l from -N to N) and radial indices (p from 0 to N//2).

required

Returns:

Name Type Description
l, p : np.ndarray

Meshgrids of the LG mode indices actually used.

overlaps ndarray

Complex array of shape (2N+1, N//2 + 1) where overlaps[l+N, p] is overlap(Beam, LG_{l,p}), i.e. the complex overlap of Beam with the LG mode of indices (l, p).

Source code in structured_optics\tools.py
 97
 98
 99
100
101
102
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
def lg_proj(Beam, N):
    """
    Project `Beam` onto the Laguerre-Gaussian (LG) basis, with azimuthal
    index l ranging over -N..N and radial index p ranging over
    0..floor(N/2).

    Parameters
    ----------
    Beam : object
        Beam instance to decompose. Not modified.
    N : int
        Controls the range of azimuthal indices (`l` from -N to N) and
        radial indices (`p` from 0 to N//2).

    Returns
    -------
    l, p : np.ndarray
        Meshgrids of the LG mode indices actually used.
    overlaps : np.ndarray
        Complex array of shape (2N+1, N//2 + 1) where
        `overlaps[l+N, p]` is `overlap(Beam, LG_{l,p})`, i.e. the
        complex overlap of `Beam` with the LG mode of indices (l, p).
    """
    overlaps = np.zeros((int(2*N)+1, int(N/2)+1), dtype='complex')
    auxiliary_beam  = Beam.copy_clean()
    for l in np.arange(-N, N+1, 1):
        for p in range(int(N/2)+1):
            auxiliary_beam.lg(l,p)
            overlaps[l+N,p] = overlap(Beam, auxiliary_beam)
    p, l = np.meshgrid(np.arange(0, int(N/2)+1, 1), np.arange(-N, N+1, 1))
    return l, p, overlaps

hg_basis

hg_basis(Beam, N, waist=None, norm1=False)

Build an array of Hermite-Gaussian basis mode fields, for all (n, m) with n, m in 0..N.

Parameters:

Name Type Description Default
Beam object

Template Beam instance (grid, wavelength, etc. are taken from it via Beam.copy_clean()); not modified.

required
N int

Maximum HG index (inclusive) along both n and m.

required
waist float

If given, overrides the auxiliary beam's waist before generating each mode. If None (default), the template beam's own waist is used.

None
norm1 bool

If True, the whole basis array is divided by its maximum value (a single global normalization, not a per-mode one). Defaults to False.

False

Returns:

Type Description
ndarray

Complex array of shape (N+1, N+1, Beam.Dy, Beam.Dx), where basis[n, m] is the transverse Ex field of the HG(n, m) mode.

Source code in structured_optics\tools.py
129
130
131
132
133
134
135
136
137
138
139
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
167
def hg_basis(Beam, N, waist = None, norm1 = False):
    """
    Build an array of Hermite-Gaussian basis mode fields, for all
    (n, m) with n, m in 0..N.

    Parameters
    ----------
    Beam : object
        Template Beam instance (grid, wavelength, etc. are taken from
        it via `Beam.copy_clean()`); not modified.
    N : int
        Maximum HG index (inclusive) along both `n` and `m`.
    waist : float, optional
        If given, overrides the auxiliary beam's waist before
        generating each mode. If `None` (default), the template
        beam's own waist is used.
    norm1 : bool, optional
        If True, the whole basis array is divided by its maximum value
        (a single global normalization, not a per-mode one). Defaults
        to False.

    Returns
    -------
    np.ndarray
        Complex array of shape (N+1, N+1, Beam.Dy, Beam.Dx), where
        `basis[n, m]` is the transverse `Ex` field of the HG(n, m)
        mode.
    """
    aux = Beam.copy_clean()
    if waist != None:
        aux.waist = waist
    basis = np.empty((N+1, N+1, Beam.Dy, Beam.Dx), dtype = 'complex')
    for n in range(N+1):
        for m in range(N+1):
            aux.hg(n, m)
            basis[n, m] = aux.Ex
    if norm1 == True:
        basis = basis/np.max(basis)
    return basis

lg_basis

lg_basis(Beam, N, waist=None, norm1=False)

Build an array of Laguerre-Gaussian basis mode fields, indexed on an (n, m) grid (n, m in 0..N) rather than directly by (l, p).

For each (n, m), the LG mode used is LG(l, p) with l = m - n and p = min(n, m) -- i.e. moving along a row/column of the (n, m) grid sweeps through LG modes of varying azimuthal index at a fixed "diagonal" relationship to the radial index. This indexing is a convenience for building a square basis array; see the l, p computed inside the loop if you need the actual LG indices for a given (n, m).

Parameters:

Name Type Description Default
Beam object

Template Beam instance (grid, wavelength, etc. are taken from it via Beam.copy_clean()); not modified.

required
N int

Maximum index (inclusive) along both n and m.

required
waist float

If given, overrides the auxiliary beam's waist before generating each mode. If None (default), the template beam's own waist is used.

None
norm1 bool

If True, the whole basis array is divided by its maximum value (a single global normalization, not a per-mode one). Defaults to False.

False

Returns:

Type Description
ndarray

Complex array of shape (N+1, N+1, Beam.Dy, Beam.Dx), where basis[n, m] is the transverse Ex field of the LG(l=m-n, p=min(n,m)) mode.

Source code in structured_optics\tools.py
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
def lg_basis(Beam, N, waist=None, norm1=False):
    """
    Build an array of Laguerre-Gaussian basis mode fields, indexed on
    an (n, m) grid (n, m in 0..N) rather than directly by (l, p).

    For each (n, m), the LG mode used is `LG(l, p)` with
    `l = m - n` and `p = min(n, m)` -- i.e. moving along a row/column
    of the (n, m) grid sweeps through LG modes of varying azimuthal
    index at a fixed "diagonal" relationship to the radial index. This
    indexing is a convenience for building a square basis array; see
    the `l`, `p` computed inside the loop if you need the actual LG
    indices for a given (n, m).

    Parameters
    ----------
    Beam : object
        Template Beam instance (grid, wavelength, etc. are taken from
        it via `Beam.copy_clean()`); not modified.
    N : int
        Maximum index (inclusive) along both `n` and `m`.
    waist : float, optional
        If given, overrides the auxiliary beam's waist before
        generating each mode. If `None` (default), the template
        beam's own waist is used.
    norm1 : bool, optional
        If True, the whole basis array is divided by its maximum value
        (a single global normalization, not a per-mode one). Defaults
        to False.

    Returns
    -------
    np.ndarray
        Complex array of shape (N+1, N+1, Beam.Dy, Beam.Dx), where
        `basis[n, m]` is the transverse `Ex` field of the
        `LG(l=m-n, p=min(n,m))` mode.
    """
    aux = Beam.copy_clean()
    if waist != None:
        aux.waist = waist
    basis = np.empty((N+1, N+1, Beam.Dy, Beam.Dx), dtype = 'complex')
    for n in range(N+1):
        for m in range(N+1):
            l = m-n
            p = min(n,m)
            aux.lg(l, p)
            basis[n, m] = aux.Ex
    if norm1 == True:
        basis = basis/np.max(basis)
    return basis

bessel_basis

bessel_basis(Beam, Nmax, waist=None, norm1=False)

Build an array of Bessel-beam basis fields, for orders n = -Nmax..Nmax.

Parameters:

Name Type Description Default
Beam object

Template Beam instance (grid, wavelength, etc. are taken from it via Beam.copy_clean()); not modified.

required
Nmax int

Maximum Bessel order magnitude; orders from -Nmax to Nmax (inclusive) are generated, i.e. 2*Nmax + 1 modes total.

required
waist float

If given, overrides the auxiliary beam's waist before generating each mode. If None (default), the template beam's own waist is used.

None
norm1 bool

If True, the whole basis array is divided by the maximum of its absolute value (a single global normalization, not a per-mode one). Defaults to False.

False

Returns:

Type Description
ndarray

Complex array of shape (2*Nmax+1, Beam.Dy, Beam.Dx), where basis[n] is the full field of the Bessel beam of order n - Nmax.

Source code in structured_optics\tools.py
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
def bessel_basis(Beam, Nmax, waist=None, norm1=False):
    """
    Build an array of Bessel-beam basis fields, for orders
    n = -Nmax..Nmax.

    Parameters
    ----------
    Beam : object
        Template Beam instance (grid, wavelength, etc. are taken from
        it via `Beam.copy_clean()`); not modified.
    Nmax : int
        Maximum Bessel order magnitude; orders from `-Nmax` to `Nmax`
        (inclusive) are generated, i.e. `2*Nmax + 1` modes total.
    waist : float, optional
        If given, overrides the auxiliary beam's waist before
        generating each mode. If `None` (default), the template
        beam's own waist is used.
    norm1 : bool, optional
        If True, the whole basis array is divided by the maximum of
        its absolute value (a single global normalization, not a
        per-mode one). Defaults to False.

    Returns
    -------
    np.ndarray
        Complex array of shape (2*Nmax+1, Beam.Dy, Beam.Dx), where
        `basis[n]` is the full field of the Bessel beam of order
        `n - Nmax`.
    """
    aux = Beam.copy_clean()
    if waist is not None:
        aux.waist = waist
    # basis[n] = Bessel beam of order n
    basis = np.empty((2*Nmax+1, aux.Dy, aux.Dx), dtype='complex')
    for n in range(2*Nmax+1):
        aux.bessel(n-Nmax)   # or aux.bessel(n, theta=...)
        basis[n] = aux.field
    if norm1:
        basis = basis / np.max(np.abs(basis))
    return basis