Skip to content

Abcd Propagators¤

ABCDElement

dLux.layers.abcd_propagators.ABCDElement ¤

Bases: Base

An ABCD element is a layer that can be represented by an ABCD matrix. This is a base class for such elements, and should not be used directly.

UML

UML

Source code in dLux/layers/abcd_propagators.py
23
24
25
26
27
28
29
30
31
32
class ABCDElement(zdx.Base):
    """
    An ABCD element is a layer that can be represented by an ABCD matrix. This is a
    base class for such elements, and should not be used directly.

    ??? abstract "UML"
        ![UML](../../assets/uml/ABCDElement.png)
    """

    pass
ABCDFreeSpace

dLux.layers.abcd_propagators.ABCDFreeSpace ¤

Bases: ABCDElement

A free space propagation element represented by an ABCD matrix.

UML

UML

Source code in dLux/layers/abcd_propagators.py
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
60
61
62
class ABCDFreeSpace(ABCDElement):
    """
    A free space propagation element represented by an ABCD matrix.

    ??? abstract "UML"
        ![UML](../../assets/uml/ABCDFreeSpace.png)
    """

    distance: float

    def __init__(self, distance):
        """
        Parameters
        ----------
        distance : float
            The free-space propagation distance.
        """
        self.distance = np.array(distance, float)

    @property
    def abcd(self):
        """
        Returns
        -------
        matrix : Array
            The analytic ABCD matrix for free-space propagation.
        """
        return abcd.abcd_free_space(self.distance)

abcd property ¤

Returns:

Name Type Description
matrix Array

The analytic ABCD matrix for free-space propagation.

__init__(distance) ¤

Parameters:

Name Type Description Default
distance float

The free-space propagation distance.

required
Source code in dLux/layers/abcd_propagators.py
45
46
47
48
49
50
51
52
def __init__(self, distance):
    """
    Parameters
    ----------
    distance : float
        The free-space propagation distance.
    """
    self.distance = np.array(distance, float)
ABCDLens

dLux.layers.abcd_propagators.ABCDLens ¤

Bases: ABCDElement

A lens element represented by an ABCD matrix. Note this element alone does not produce the standard 'pupil-focal Fourier relationship' as that is between the front and back focal planes. To represent a true pupil-focal plane propagation, apply a free space propagation of the focal length both before and after the lens, or use the ABCDConjugatePlane element.

UML

UML

Source code in dLux/layers/abcd_propagators.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
95
96
class ABCDLens(ABCDElement):
    """
    A lens element represented by an ABCD matrix. Note this element alone does not
    produce the standard 'pupil-focal Fourier relationship' as that is between the front
    and back focal planes. To represent a true pupil-focal plane propagation, apply a
    free space propagation of the focal length both before _and_ after the lens, or use
    the ABCDConjugatePlane element.

    ??? abstract "UML"
        ![UML](../../assets/uml/ABCDLens.png)
    """

    focal_length: float

    def __init__(self, focal_length):
        """
        Parameters
        ----------
        focal_length : float
            The lens focal length.
        """
        self.focal_length = np.array(focal_length, float)

    @property
    def abcd(self):
        """
        Returns
        -------
        matrix : Array
            The analytic ABCD matrix for a lens.
        """
        return abcd.abcd_lens(self.focal_length)

abcd property ¤

Returns:

Name Type Description
matrix Array

The analytic ABCD matrix for a lens.

__init__(focal_length) ¤

Parameters:

Name Type Description Default
focal_length float

The lens focal length.

required
Source code in dLux/layers/abcd_propagators.py
79
80
81
82
83
84
85
86
def __init__(self, focal_length):
    """
    Parameters
    ----------
    focal_length : float
        The lens focal length.
    """
    self.focal_length = np.array(focal_length, float)
ABCDMirror

dLux.layers.abcd_propagators.ABCDMirror ¤

Bases: ABCDElement

A mirror element represented by an ABCD matrix.

UML

UML

Source code in dLux/layers/abcd_propagators.py
 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
class ABCDMirror(ABCDElement):
    """
    A mirror element represented by an ABCD matrix.

    ??? abstract "UML"
        ![UML](../../assets/uml/ABCDMirror.png)
    """

    radius: float

    def __init__(self, radius):
        """
        Parameters
        ----------
        radius : float
            The mirror radius of curvature.
        """
        self.radius = np.array(radius, float)

    @property
    def abcd(self):
        """
        Returns
        -------
        matrix : Array
            The analytic ABCD matrix for a mirror.
        """
        return abcd.abcd_mirror(self.radius)

abcd property ¤

Returns:

Name Type Description
matrix Array

The analytic ABCD matrix for a mirror.

__init__(radius) ¤

Parameters:

Name Type Description Default
radius float

The mirror radius of curvature.

required
Source code in dLux/layers/abcd_propagators.py
109
110
111
112
113
114
115
116
def __init__(self, radius):
    """
    Parameters
    ----------
    radius : float
        The mirror radius of curvature.
    """
    self.radius = np.array(radius, float)
ABCDConjugatePlane

dLux.layers.abcd_propagators.ABCDConjugatePlane ¤

Bases: ABCDElement

A conjugate plane element represented by an ABCD matrix. This produces the classic 'pupil-focal Fourier relationship' seen in fourier/physical optics.

UML

UML

Source code in dLux/layers/abcd_propagators.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
class ABCDConjugatePlane(ABCDElement):
    """
    A conjugate plane element represented by an ABCD matrix. This produces the classic
    'pupil-focal Fourier relationship' seen in fourier/physical optics.

    ??? abstract "UML"
        ![UML](../../assets/uml/ABCDConjugatePlane.png)
    """

    focal_length: float

    def __init__(self, focal_length):
        """
        Parameters
        ----------
        focal_length : float
            The effective focal length that defines the conjugate-plane transform.
        """
        self.focal_length = np.array(focal_length, float)

    @property
    def abcd(self):
        """
        Returns
        -------
        matrix : Array
            The analytic ABCD matrix for a conjugate-plane propagation.
        """
        return abcd.abcd_fraunhofer(self.focal_length)

abcd property ¤

Returns:

Name Type Description
matrix Array

The analytic ABCD matrix for a conjugate-plane propagation.

__init__(focal_length) ¤

Parameters:

Name Type Description Default
focal_length float

The effective focal length that defines the conjugate-plane transform.

required
Source code in dLux/layers/abcd_propagators.py
140
141
142
143
144
145
146
147
def __init__(self, focal_length):
    """
    Parameters
    ----------
    focal_length : float
        The effective focal length that defines the conjugate-plane transform.
    """
    self.focal_length = np.array(focal_length, float)
ABCDPropagator

dLux.layers.abcd_propagators.ABCDPropagator ¤

Bases: OpticalLayer

Propagator defined by a composition of ABCD elements.

UML

UML

Attributes:

Name Type Description
ABCDs dict

Dictionary of ABCD elements in propagation order.

spec CoordSpec | PadSpec

Output coordinate specification.

Source code in dLux/layers/abcd_propagators.py
163
164
165
166
167
168
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
class ABCDPropagator(OpticalLayer):
    """
    Propagator defined by a composition of ABCD elements.

    ??? abstract "UML"
        ![UML](../../assets/uml/ABCDPropagator.png)

    Attributes
    ----------
    ABCDs : dict
        Dictionary of ABCD elements in propagation order.
    spec : CoordSpec | PadSpec
        Output coordinate specification.
    """

    ABCDs: dict
    spec: CoordSpec

    def __init__(self, ABCDs, spec):
        """
        Parameters
        ----------
        ABCDs : list[ABCDElement] | dict[str, ABCDElement]
            ABCD elements to compose into a single propagation transform.
        spec : CoordSpec | PadSpec
            Output coordinate specification.
        """
        self.ABCDs = dlu.list2dictionary(ABCDs, True, allowed_types=(ABCDElement,))
        self.spec = spec

    def __getattr__(self, key):
        """Resolve missing attributes via `spec` or child ABCD elements."""
        if hasattr(self.spec, key):
            return getattr(self.spec, key)
        if key in self.ABCDs.keys():
            return self.ABCDs[key]
        for layer in list(self.ABCDs.values()):
            if hasattr(layer, key):
                return getattr(layer, key)
        raise dlu.missing_attribute_error(self, key, list(self.ABCDs.keys()))

    @property
    def abcd(self):
        """
        Returns
        -------
        matrix : Array
            The composed ABCD matrix for this propagator.
        """
        return abcd.compose_abcd([m.abcd for m in self.ABCDs.values()])

abcd property ¤

Returns:

Name Type Description
matrix Array

The composed ABCD matrix for this propagator.

__getattr__(key) ¤

Resolve missing attributes via spec or child ABCD elements.

Source code in dLux/layers/abcd_propagators.py
193
194
195
196
197
198
199
200
201
202
def __getattr__(self, key):
    """Resolve missing attributes via `spec` or child ABCD elements."""
    if hasattr(self.spec, key):
        return getattr(self.spec, key)
    if key in self.ABCDs.keys():
        return self.ABCDs[key]
    for layer in list(self.ABCDs.values()):
        if hasattr(layer, key):
            return getattr(layer, key)
    raise dlu.missing_attribute_error(self, key, list(self.ABCDs.keys()))

__init__(ABCDs, spec) ¤

Parameters:

Name Type Description Default
ABCDs list[ABCDElement] | dict[str, ABCDElement]

ABCD elements to compose into a single propagation transform.

required
spec CoordSpec | PadSpec

Output coordinate specification.

required
Source code in dLux/layers/abcd_propagators.py
181
182
183
184
185
186
187
188
189
190
191
def __init__(self, ABCDs, spec):
    """
    Parameters
    ----------
    ABCDs : list[ABCDElement] | dict[str, ABCDElement]
        ABCD elements to compose into a single propagation transform.
    spec : CoordSpec | PadSpec
        Output coordinate specification.
    """
    self.ABCDs = dlu.list2dictionary(ABCDs, True, allowed_types=(ABCDElement,))
    self.spec = spec
MFTPropagator

dLux.layers.abcd_propagators.MFTPropagator ¤

Bases: ABCDPropagator

A matrix Fourier transform (MFT) propagator represented by an ABCD matrix.

Note: Always returns a wavefront in an 'Intermediate' plane, even if the propagation is to a conjugate plane. Future ABCDWavefronts may enable better plane tracking, but the present Wavefront class is not compatible with this formulation.

UML

UML

Parameters:

Name Type Description Default
ABCDs

A list of ABCD elements to compose into the overall ABCD matrix for the propagation.

required
spec

The coordinate specification of the output wavefront.

required
Source code in dLux/layers/abcd_propagators.py
215
216
217
218
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
259
260
261
262
263
class MFTPropagator(ABCDPropagator):
    """
    A matrix Fourier transform (MFT) propagator represented by an ABCD matrix.

    Note: Always returns a wavefront in an 'Intermediate' plane, even if the
    propagation is to a conjugate plane. Future ABCDWavefronts may enable better plane
    tracking, but the present Wavefront class is not compatible with this formulation.

    ??? abstract "UML"
        ![UML](../../assets/uml/MFTPropagator.png)

    Parameters
    ----------
    ABCDs: list[ABCDElement]
        A list of ABCD elements to compose into the overall ABCD matrix for the
        propagation.
    spec: CoordSpec
        The coordinate specification of the output wavefront.
    """

    def __call__(self, wavefront):
        """
        Propagate a wavefront using an LCT-based matrix Fourier transform.

        Parameters
        ----------
        wavefront : Wavefront
            Input wavefront to propagate.

        Returns
        -------
        wavefront : Wavefront
            Propagated wavefront with updated field and output specification.
        """
        # Define input-output coordinates
        spec_in = wavefront.spec
        spec_out = self.spec

        # Propagate the field
        field = lct.lct_prop(
            u_in=wavefront.phasor,
            spec_in=spec_in.xs,
            spec_out=spec_out.xs,
            lam=wavefront.wavelength,
            ABCD=self.abcd,
        )

        # Update wavefront
        return wavefront.set(phasor=field).set_spec(spec_out)

__call__(wavefront) ¤

Propagate a wavefront using an LCT-based matrix Fourier transform.

Parameters:

Name Type Description Default
wavefront Wavefront

Input wavefront to propagate.

required

Returns:

Name Type Description
wavefront Wavefront

Propagated wavefront with updated field and output specification.

Source code in dLux/layers/abcd_propagators.py
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
def __call__(self, wavefront):
    """
    Propagate a wavefront using an LCT-based matrix Fourier transform.

    Parameters
    ----------
    wavefront : Wavefront
        Input wavefront to propagate.

    Returns
    -------
    wavefront : Wavefront
        Propagated wavefront with updated field and output specification.
    """
    # Define input-output coordinates
    spec_in = wavefront.spec
    spec_out = self.spec

    # Propagate the field
    field = lct.lct_prop(
        u_in=wavefront.phasor,
        spec_in=spec_in.xs,
        spec_out=spec_out.xs,
        lam=wavefront.wavelength,
        ABCD=self.abcd,
    )

    # Update wavefront
    return wavefront.set(phasor=field).set_spec(spec_out)
FFTPropagator

dLux.layers.abcd_propagators.FFTPropagator ¤

Bases: ABCDPropagator

FFT-based ABCD propagator with optional padding and cropping.

Note: Always returns a wavefront in an 'Intermediate' plane, even if the propagation is to a conjugate plane. Future ABCDWavefronts may enable better plane tracking, but the present Wavefront class is not compatible with this formulation.

UML

UML

Parameters:

Name Type Description Default
ABCDs list[ABCDElement] | dict[str, ABCDElement]

ABCD elements to compose into a single propagation transform.

required
spec CoordSpec | PadSpec

Output coordinate specification. If CoordSpec is provided, d must be None.

required
Source code in dLux/layers/abcd_propagators.py
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
class FFTPropagator(ABCDPropagator):
    """
    FFT-based ABCD propagator with optional padding and cropping.

    Note: Always returns a wavefront in an 'Intermediate' plane, even if the
    propagation is to a conjugate plane. Future ABCDWavefronts may enable better plane
    tracking, but the present Wavefront class is not compatible with this formulation.

    ??? abstract "UML"
        ![UML](../../assets/uml/FFTPropagator.png)

    Parameters
    ----------
    ABCDs : list[ABCDElement] | dict[str, ABCDElement]
        ABCD elements to compose into a single propagation transform.
    spec : CoordSpec | PadSpec
        Output coordinate specification. If `CoordSpec` is provided, `d` must be None.
    """

    def __init__(self, ABCDs, spec):
        """
        Parameters
        ----------
        ABCDs : list[ABCDElement] | dict[str, ABCDElement]
            ABCD elements to compose into a single propagation transform.
        spec : CoordSpec | PadSpec
            Output coordinate specification. If `CoordSpec` is provided, `d` must be
            None.
        """
        if isinstance(spec, CoordSpec) and (spec.d is not None):
            raise ValueError("FFTPropagator CoordSpec can not specify d.")
        super().__init__(ABCDs=ABCDs, spec=spec)

    def __call__(self, wavefront):
        """
        Propagate a wavefront using an FFT-based LCT approximation.

        Parameters
        ----------
        wavefront : Wavefront
            Input wavefront to propagate.

        Returns
        -------
        wavefront : Wavefront
            Propagated wavefront with updated field and sampling metadata.
        """

        # Get the input spec
        spec_in = wavefront.spec
        lam = wavefront.wavelength

        # Handle the two spec options
        if isinstance(self.spec, CoordSpec):
            n_padded = self.spec.n
        else:
            n_padded = spec_in.n * self.spec.pad

        # Get the effective focal length for the ABCD system
        fl = abcd.abcd_effective_focal_length(self.abcd)

        # Calculate the phase ramp for the FFT propagation offset
        d_fft, c_fft = dlu.fft_spec(n_padded, spec_in.d, lam, fl)
        in_ramp = dlu.fft_phase_ramp(spec_in.xs, lam, c_fft - self.spec.c, fl)

        # Calculate the output phase ramp correction
        spec_out = CoordSpec(n=n_padded, c=self.spec.c, d=d_fft)

        # FFT-based LCT propagation
        field, spec_out_xys = lct.lct_prop_fft(
            u_in=wavefront.phasor * in_ramp,
            spec_in=wavefront.spec.xs,
            lam=wavefront.wavelength,
            ABCD=self.abcd,
            npad=spec_out.n,
        )

        # Apply the crop if specified
        if isinstance(self.spec, PadSpec) and self.spec.crop > 1:
            n_out = field.shape[0] // self.spec.crop
            field = dlu.crop_to(field, n_out)

        # # Get the output coordinates
        xs_out, ys_out = spec_out_xys
        dx_out = xs_out[1] - xs_out[0]

        # Update wavefront
        return wavefront.set(phasor=field, pixel_scale=dx_out, center=self.spec.c)

__call__(wavefront) ¤

Propagate a wavefront using an FFT-based LCT approximation.

Parameters:

Name Type Description Default
wavefront Wavefront

Input wavefront to propagate.

required

Returns:

Name Type Description
wavefront Wavefront

Propagated wavefront with updated field and sampling metadata.

Source code in dLux/layers/abcd_propagators.py
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
def __call__(self, wavefront):
    """
    Propagate a wavefront using an FFT-based LCT approximation.

    Parameters
    ----------
    wavefront : Wavefront
        Input wavefront to propagate.

    Returns
    -------
    wavefront : Wavefront
        Propagated wavefront with updated field and sampling metadata.
    """

    # Get the input spec
    spec_in = wavefront.spec
    lam = wavefront.wavelength

    # Handle the two spec options
    if isinstance(self.spec, CoordSpec):
        n_padded = self.spec.n
    else:
        n_padded = spec_in.n * self.spec.pad

    # Get the effective focal length for the ABCD system
    fl = abcd.abcd_effective_focal_length(self.abcd)

    # Calculate the phase ramp for the FFT propagation offset
    d_fft, c_fft = dlu.fft_spec(n_padded, spec_in.d, lam, fl)
    in_ramp = dlu.fft_phase_ramp(spec_in.xs, lam, c_fft - self.spec.c, fl)

    # Calculate the output phase ramp correction
    spec_out = CoordSpec(n=n_padded, c=self.spec.c, d=d_fft)

    # FFT-based LCT propagation
    field, spec_out_xys = lct.lct_prop_fft(
        u_in=wavefront.phasor * in_ramp,
        spec_in=wavefront.spec.xs,
        lam=wavefront.wavelength,
        ABCD=self.abcd,
        npad=spec_out.n,
    )

    # Apply the crop if specified
    if isinstance(self.spec, PadSpec) and self.spec.crop > 1:
        n_out = field.shape[0] // self.spec.crop
        field = dlu.crop_to(field, n_out)

    # # Get the output coordinates
    xs_out, ys_out = spec_out_xys
    dx_out = xs_out[1] - xs_out[0]

    # Update wavefront
    return wavefront.set(phasor=field, pixel_scale=dx_out, center=self.spec.c)

__init__(ABCDs, spec) ¤

Parameters:

Name Type Description Default
ABCDs list[ABCDElement] | dict[str, ABCDElement]

ABCD elements to compose into a single propagation transform.

required
spec CoordSpec | PadSpec

Output coordinate specification. If CoordSpec is provided, d must be None.

required
Source code in dLux/layers/abcd_propagators.py
285
286
287
288
289
290
291
292
293
294
295
296
297
def __init__(self, ABCDs, spec):
    """
    Parameters
    ----------
    ABCDs : list[ABCDElement] | dict[str, ABCDElement]
        ABCD elements to compose into a single propagation transform.
    spec : CoordSpec | PadSpec
        Output coordinate specification. If `CoordSpec` is provided, `d` must be
        None.
    """
    if isinstance(spec, CoordSpec) and (spec.d is not None):
        raise ValueError("FFTPropagator CoordSpec can not specify d.")
    super().__init__(ABCDs=ABCDs, spec=spec)
ASMPropagator

dLux.layers.abcd_propagators.ASMPropagator ¤

Bases: OpticalLayer

Angular Spectrum Method (ASM) propagator.

Note: Always returns a wavefront in an 'Intermediate' plane, even if the propagation is to a conjugate plane. Future ABCDWavefronts may enable better plane tracking, but the present Wavefront class is not compatible with this formulation.

UML

UML

Source code in dLux/layers/abcd_propagators.py
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
class ASMPropagator(OpticalLayer):
    """
    Angular Spectrum Method (ASM) propagator.

    Note: Always returns a wavefront in an 'Intermediate' plane, even if the
    propagation is to a conjugate plane. Future ABCDWavefronts may enable better plane
    tracking, but the present Wavefront class is not compatible with this formulation.

    ??? abstract "UML"
        ![UML](../../assets/uml/ASMPropagator.png)
    """

    distance: float
    spec: CoordSpec

    def __init__(self, distance, spec):
        """
        Parameters
        ----------
        distance : float
            Propagation distance.
        spec : CoordSpec | PadSpec
            Output specification. If `CoordSpec` is provided, `d` and `c` must be None.
        """
        self.distance = float(distance)
        if isinstance(spec, CoordSpec):
            if spec.d is not None or spec.c is not None:
                raise ValueError("ASMPropagator CoordSpec can not specify d or c.")
        self.spec = spec

    def __getattr__(self, key):
        """Resolve missing attributes via `spec`."""
        if hasattr(self.spec, key):
            return getattr(self.spec, key)
        raise dlu.missing_attribute_error(self, key)

    def __call__(self, wavefront):
        """
        Propagate a wavefront using the angular spectrum method.

        Parameters
        ----------
        wavefront : Wavefront
            Input wavefront to propagate.

        Returns
        -------
        wavefront : Wavefront
            Propagated wavefront with updated field.
        """

        # Get padding
        if isinstance(self.spec, CoordSpec):
            n_padded = self.spec.n
        else:
            n_padded = wavefront.npixels * self.spec.pad

        # Propagate the field
        field = asm.asm_prop(
            u_in=wavefront.phasor,
            spec_in=wavefront.xs,
            lam=wavefront.wavelength,
            z=self.distance,
            npad=n_padded,
            crop=False,
        )

        # Apply the crop if specified
        if isinstance(self.spec, PadSpec) and self.spec.crop > 1:
            n_out = field.shape[0] // self.spec.crop
            field = dlu.crop_to(field, n_out)

        # Update wavefront
        return wavefront.set(phasor=field)

__call__(wavefront) ¤

Propagate a wavefront using the angular spectrum method.

Parameters:

Name Type Description Default
wavefront Wavefront

Input wavefront to propagate.

required

Returns:

Name Type Description
wavefront Wavefront

Propagated wavefront with updated field.

Source code in dLux/layers/abcd_propagators.py
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
def __call__(self, wavefront):
    """
    Propagate a wavefront using the angular spectrum method.

    Parameters
    ----------
    wavefront : Wavefront
        Input wavefront to propagate.

    Returns
    -------
    wavefront : Wavefront
        Propagated wavefront with updated field.
    """

    # Get padding
    if isinstance(self.spec, CoordSpec):
        n_padded = self.spec.n
    else:
        n_padded = wavefront.npixels * self.spec.pad

    # Propagate the field
    field = asm.asm_prop(
        u_in=wavefront.phasor,
        spec_in=wavefront.xs,
        lam=wavefront.wavelength,
        z=self.distance,
        npad=n_padded,
        crop=False,
    )

    # Apply the crop if specified
    if isinstance(self.spec, PadSpec) and self.spec.crop > 1:
        n_out = field.shape[0] // self.spec.crop
        field = dlu.crop_to(field, n_out)

    # Update wavefront
    return wavefront.set(phasor=field)

__getattr__(key) ¤

Resolve missing attributes via spec.

Source code in dLux/layers/abcd_propagators.py
386
387
388
389
390
def __getattr__(self, key):
    """Resolve missing attributes via `spec`."""
    if hasattr(self.spec, key):
        return getattr(self.spec, key)
    raise dlu.missing_attribute_error(self, key)

__init__(distance, spec) ¤

Parameters:

Name Type Description Default
distance float

Propagation distance.

required
spec CoordSpec | PadSpec

Output specification. If CoordSpec is provided, d and c must be None.

required
Source code in dLux/layers/abcd_propagators.py
371
372
373
374
375
376
377
378
379
380
381
382
383
384
def __init__(self, distance, spec):
    """
    Parameters
    ----------
    distance : float
        Propagation distance.
    spec : CoordSpec | PadSpec
        Output specification. If `CoordSpec` is provided, `d` and `c` must be None.
    """
    self.distance = float(distance)
    if isinstance(spec, CoordSpec):
        if spec.d is not None or spec.c is not None:
            raise ValueError("ASMPropagator CoordSpec can not specify d or c.")
    self.spec = spec