Skip to content

Optical Layers¤

BaseLayer

dLux.layers.optical_layers.BaseLayer ¤

Bases: Base

Abstract base class for all dLux layers.

Layer objects define a callable transform interface that maps one target object to another (for example Wavefront -> Wavefront or PSF -> PSF).

UML

UML

Source code in dLux/layers/optical_layers.py
26
27
28
29
30
31
32
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
60
class BaseLayer(zdx.Base):
    """
    Abstract base class for all dLux layers.

    Layer objects define a callable transform interface that maps one target
    object to another (for example Wavefront -> Wavefront or PSF -> PSF).

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

    @abstractmethod
    def __call__(self: BaseLayer, target: Any) -> Any:  # pragma: no cover
        pass

    def apply(self: BaseLayer, target: Any) -> Any:
        """
        Backwards compatibility alias for `__call__`.

        Parameters
        ----------
        target : Any
            The object to operate on.

        Returns
        -------
        result : Any
            The transformed object.
        """
        return self(target)

    def __init_subclass__(cls, **kwargs):
        """Automatically inherit __call__ docstring from parent if child has none."""
        super().__init_subclass__(**kwargs)
        dlu.helpers.inherit_docstrings(cls, ["__call__"])

__init_subclass__(**kwargs) ¤

Automatically inherit call docstring from parent if child has none.

Source code in dLux/layers/optical_layers.py
57
58
59
60
def __init_subclass__(cls, **kwargs):
    """Automatically inherit __call__ docstring from parent if child has none."""
    super().__init_subclass__(**kwargs)
    dlu.helpers.inherit_docstrings(cls, ["__call__"])

apply(target) ¤

Backwards compatibility alias for __call__.

Parameters:

Name Type Description Default
target Any

The object to operate on.

required

Returns:

Name Type Description
result Any

The transformed object.

Source code in dLux/layers/optical_layers.py
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
def apply(self: BaseLayer, target: Any) -> Any:
    """
    Backwards compatibility alias for `__call__`.

    Parameters
    ----------
    target : Any
        The object to operate on.

    Returns
    -------
    result : Any
        The transformed object.
    """
    return self(target)
OpticalLayer

dLux.layers.optical_layers.OpticalLayer ¤

Bases: BaseLayer

The base optical layer class. Optical layer classes operate on Wavefront objects through their apply method, and are stored by the OpticalSystem classes.

UML

UML

Source code in dLux/layers/optical_layers.py
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
class OpticalLayer(BaseLayer):
    """
    The base optical layer class. Optical layer classes operate on `Wavefront` objects
    through their `apply` method, and are stored by the `OpticalSystem` classes.

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

    @abstractmethod
    def __call__(
        self: OpticalLayer, wavefront: Wavefront
    ) -> Wavefront:  # pragma: no cover
        """
        Applies the layer to the wavefront.

        Parameters
        ----------
        wavefront : Wavefront
            The wavefront to operate on.

        Returns
        -------
        wavefront : Wavefront
            The transformed wavefront.
        """

__call__(wavefront) abstractmethod ¤

Applies the layer to the wavefront.

Parameters:

Name Type Description Default
wavefront Wavefront

The wavefront to operate on.

required

Returns:

Name Type Description
wavefront Wavefront

The transformed wavefront.

Source code in dLux/layers/optical_layers.py
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
@abstractmethod
def __call__(
    self: OpticalLayer, wavefront: Wavefront
) -> Wavefront:  # pragma: no cover
    """
    Applies the layer to the wavefront.

    Parameters
    ----------
    wavefront : Wavefront
        The wavefront to operate on.

    Returns
    -------
    wavefront : Wavefront
        The transformed wavefront.
    """
TransmissiveLayer

dLux.layers.optical_layers.TransmissiveLayer ¤

Bases: OpticalLayer

Base class to hold transmissive layers imbuing them with a transmission and normalise parameter.

UML

UML

Attributes:

Name Type Description
transmission Array

The Array of transmission values to be applied to the input wavefront.

normalise bool

Whether to normalise the wavefront after passing through the optic.

Source code in dLux/layers/optical_layers.py
 91
 92
 93
 94
 95
 96
 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
128
129
130
131
132
133
134
class TransmissiveLayer(OpticalLayer):
    """
    Base class to hold transmissive layers imbuing them with a transmission and
    normalise parameter.

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

    Attributes
    ----------
    transmission: Array
        The Array of transmission values to be applied to the input wavefront.
    normalise: bool
        Whether to normalise the wavefront after passing through the optic.
    """

    transmission: Array
    normalise: bool

    def __init__(
        self: TransmissiveLayer,
        transmission: Array = None,
        normalise: bool = False,
        **kwargs,
    ):
        """
        Parameters
        ----------
        transmission: Array = None
            The array of transmission values to be applied to the input wavefront.
        normalise : bool = False
            Whether to normalise the wavefront after passing through the optic.
        """
        if transmission is not None:
            transmission = np.asarray(transmission, dtype=float)
        self.transmission = transmission
        self.normalise = bool(normalise)
        super().__init__(**kwargs)

    def __call__(self: TransmissiveLayer, wavefront: Wavefront) -> Wavefront:
        wavefront *= self.transmission
        if self.normalise:
            wavefront = wavefront.normalise()
        return wavefront

__init__(transmission=None, normalise=False, **kwargs) ¤

Parameters:

Name Type Description Default
transmission Array

The array of transmission values to be applied to the input wavefront.

None
normalise bool = False

Whether to normalise the wavefront after passing through the optic.

False
Source code in dLux/layers/optical_layers.py
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
def __init__(
    self: TransmissiveLayer,
    transmission: Array = None,
    normalise: bool = False,
    **kwargs,
):
    """
    Parameters
    ----------
    transmission: Array = None
        The array of transmission values to be applied to the input wavefront.
    normalise : bool = False
        Whether to normalise the wavefront after passing through the optic.
    """
    if transmission is not None:
        transmission = np.asarray(transmission, dtype=float)
    self.transmission = transmission
    self.normalise = bool(normalise)
    super().__init__(**kwargs)
AberratedLayer

dLux.layers.optical_layers.AberratedLayer ¤

Bases: OpticalLayer

Optical layer for holding static aberrations. Aberrations can be applied as either a phase or OPD, or both.

UML

UML

Attributes:

Name Type Description
opd (Array, metres)

The Array of OPD values to be applied to the input wavefront.

phase (Array, radians)

The Array of phase values to be applied to the input wavefront.

Source code in dLux/layers/optical_layers.py
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
class AberratedLayer(OpticalLayer):
    """
    Optical layer for holding static aberrations. Aberrations can be applied as either
    a phase or OPD, or both.

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

    Attributes
    ----------
    opd : Array, metres
        The Array of OPD values to be applied to the input wavefront.
    phase : Array, radians
        The Array of phase values to be applied to the input wavefront.
    """

    opd: Array
    phase: Array

    def __init__(
        self: AberratedLayer,
        opd: Array = None,
        phase: Array = None,
        **kwargs,
    ):
        """
        Parameters
        ----------
        opd : Array, metres = None
            The Array of OPD values to be applied to the input wavefront.
        phase : Array, radians = None
            The Array of phase values to be applied to the input wavefront.
        """
        if opd is not None:
            opd = np.asarray(opd, dtype=float)
        self.opd = opd

        if phase is not None:
            phase = np.asarray(phase, dtype=float)
        self.phase = phase

        if self.opd is not None and self.phase is not None:
            if self.opd.shape != self.phase.shape:
                raise ValueError(
                    "opd and phase must have the same shape. Got "
                    f"shapes {self.opd.shape} and {self.phase.shape}."
                )
        super().__init__(**kwargs)

    def __call__(self: AberratedLayer, wavefront: Wavefront) -> Wavefront:
        wavefront = wavefront.add_opd(self.opd)
        wavefront = wavefront.add_phase(self.phase)
        return wavefront

__init__(opd=None, phase=None, **kwargs) ¤

Parameters:

Name Type Description Default
opd Array, metres = None

The Array of OPD values to be applied to the input wavefront.

None
phase Array, radians = None

The Array of phase values to be applied to the input wavefront.

None
Source code in dLux/layers/optical_layers.py
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
def __init__(
    self: AberratedLayer,
    opd: Array = None,
    phase: Array = None,
    **kwargs,
):
    """
    Parameters
    ----------
    opd : Array, metres = None
        The Array of OPD values to be applied to the input wavefront.
    phase : Array, radians = None
        The Array of phase values to be applied to the input wavefront.
    """
    if opd is not None:
        opd = np.asarray(opd, dtype=float)
    self.opd = opd

    if phase is not None:
        phase = np.asarray(phase, dtype=float)
    self.phase = phase

    if self.opd is not None and self.phase is not None:
        if self.opd.shape != self.phase.shape:
            raise ValueError(
                "opd and phase must have the same shape. Got "
                f"shapes {self.opd.shape} and {self.phase.shape}."
            )
    super().__init__(**kwargs)
BasisLayer

dLux.layers.optical_layers.BasisLayer ¤

Bases: OpticalLayer

An OpticalLayer class that holds a set of basis vectors and coefficients, which are dot-producted at run time to produce the output. The basis can be applied as either a phase or OPD, by setting the as_phase attribute.

UML

UML

Attributes:

Name Type Description
basis Array | list

The set of basis vectors. Should in general be a 3 dimensional array.

coefficients Array

The array of coefficients to be applied to each basis vector.

as_phase bool = False

Whether to apply the basis as a phase or OPD. If True the output is applied as a phase, else it is applied as an OPD.

Source code in dLux/layers/optical_layers.py
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
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
264
265
266
267
268
269
270
271
class BasisLayer(OpticalLayer):
    """
    An OpticalLayer class that holds a set of basis vectors and coefficients, which are
    dot-producted at run time to produce the output. The basis can be applied as either
    a phase or OPD, by setting the `as_phase` attribute.

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

    Attributes
    ----------
    basis: Array | list
        The set of basis vectors. Should in general be a 3 dimensional array.
    coefficients: Array
        The array of coefficients to be applied to each basis vector.
    as_phase: bool = False
        Whether to apply the basis as a phase or OPD. If True the output is applied as
        a phase, else it is applied as an OPD.
    """

    basis: Array | list
    coefficients: Array
    as_phase: bool

    # NOTE: We need the None basis input for aberrated apertures
    def __init__(
        self: BasisLayer,
        basis: Array = None,
        coefficients: Array = None,
        as_phase: bool = False,
        **kwargs,
    ):
        """
        Parameters
        ----------
        basis: Array | list = None
            The set of basis vectors. Should in general be a 3 dimensional array.
        coefficients: Array = None
            The Array of coefficients to be applied to each basis vector. Defaults
            to zeros if `basis` is provided and `coefficients` is None.
        as_phase: bool = False
            Whether to apply the basis as a phase or OPD. If True the output is applied
            as a phase, else it is applied as an OPD.
        """
        super().__init__(**kwargs)

        if basis is not None:
            basis = np.asarray(basis, dtype=float)
            if coefficients is None:
                coefficients = np.zeros(basis.shape[:-2])
            else:
                coefficients = np.asarray(coefficients, dtype=float)
                if basis.shape[:-2] != coefficients.shape:
                    raise ValueError(
                        "The number of basis vectors must be equal to "
                        "the number of coefficients."
                    )

        self.basis = basis
        self.coefficients = coefficients
        self.as_phase = bool(as_phase)

    def eval_basis(self: BasisLayer) -> Array:
        """
        Calculates the dot product of the basis vectors and coefficients.

        Returns
        -------
        output : Array
            The output of the dot product between the basis vectors and coefficients.
        """
        return dlu.eval_basis(self.basis, self.coefficients)

    def __call__(self: BasisLayer, wavefront: Wavefront) -> Wavefront:
        output = self.eval_basis()
        if self.as_phase:
            wavefront = wavefront.add_phase(output)
        else:
            wavefront = wavefront.add_opd(output)
        return wavefront

__init__(basis=None, coefficients=None, as_phase=False, **kwargs) ¤

Parameters:

Name Type Description Default
basis Array

The set of basis vectors. Should in general be a 3 dimensional array.

None
coefficients Array

The Array of coefficients to be applied to each basis vector. Defaults to zeros if basis is provided and coefficients is None.

None
as_phase bool

Whether to apply the basis as a phase or OPD. If True the output is applied as a phase, else it is applied as an OPD.

False
Source code in dLux/layers/optical_layers.py
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
def __init__(
    self: BasisLayer,
    basis: Array = None,
    coefficients: Array = None,
    as_phase: bool = False,
    **kwargs,
):
    """
    Parameters
    ----------
    basis: Array | list = None
        The set of basis vectors. Should in general be a 3 dimensional array.
    coefficients: Array = None
        The Array of coefficients to be applied to each basis vector. Defaults
        to zeros if `basis` is provided and `coefficients` is None.
    as_phase: bool = False
        Whether to apply the basis as a phase or OPD. If True the output is applied
        as a phase, else it is applied as an OPD.
    """
    super().__init__(**kwargs)

    if basis is not None:
        basis = np.asarray(basis, dtype=float)
        if coefficients is None:
            coefficients = np.zeros(basis.shape[:-2])
        else:
            coefficients = np.asarray(coefficients, dtype=float)
            if basis.shape[:-2] != coefficients.shape:
                raise ValueError(
                    "The number of basis vectors must be equal to "
                    "the number of coefficients."
                )

    self.basis = basis
    self.coefficients = coefficients
    self.as_phase = bool(as_phase)

eval_basis() ¤

Calculates the dot product of the basis vectors and coefficients.

Returns:

Name Type Description
output Array

The output of the dot product between the basis vectors and coefficients.

Source code in dLux/layers/optical_layers.py
254
255
256
257
258
259
260
261
262
263
def eval_basis(self: BasisLayer) -> Array:
    """
    Calculates the dot product of the basis vectors and coefficients.

    Returns
    -------
    output : Array
        The output of the dot product between the basis vectors and coefficients.
    """
    return dlu.eval_basis(self.basis, self.coefficients)
Tilt

dLux.layers.optical_layers.Tilt ¤

Bases: OpticalLayer

Tilts the wavefront by the input (x, y) angles.

UML

UML

Attributes:

Name Type Description
angles (Array, radians)

The (x, y) angles by which to tilt the wavefront.

Source code in dLux/layers/optical_layers.py
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
class Tilt(OpticalLayer):
    """
    Tilts the wavefront by the input (x, y) angles.

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

    Attributes
    ----------
    angles : Array, radians
        The (x, y) angles by which to tilt the wavefront.
    """

    angles: Array

    def __init__(self: Tilt, angles: Array):
        """
        Parameters
        ----------
        angles : Array, radians
            The (x, y) angles by which to tilt the wavefront.
        """
        super().__init__()
        self.angles = np.asarray(angles, dtype=float)

        if self.angles.shape != (2,):
            raise ValueError("angles must be a 1d array of shape (2,).")

    def __call__(self: Tilt, wavefront: Wavefront) -> Wavefront:
        return wavefront.tilt(self.angles)

__init__(angles) ¤

Parameters:

Name Type Description Default
angles (Array, radians)

The (x, y) angles by which to tilt the wavefront.

required
Source code in dLux/layers/optical_layers.py
289
290
291
292
293
294
295
296
297
298
299
300
def __init__(self: Tilt, angles: Array):
    """
    Parameters
    ----------
    angles : Array, radians
        The (x, y) angles by which to tilt the wavefront.
    """
    super().__init__()
    self.angles = np.asarray(angles, dtype=float)

    if self.angles.shape != (2,):
        raise ValueError("angles must be a 1d array of shape (2,).")
Normalise

dLux.layers.optical_layers.Normalise ¤

Bases: OpticalLayer

Normalises the wavefront to unit intensity.

UML

UML

Source code in dLux/layers/optical_layers.py
306
307
308
309
310
311
312
313
314
315
class Normalise(OpticalLayer):
    """
    Normalises the wavefront to unit intensity.

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

    def __call__(self: Normalise, wavefront: Wavefront) -> Wavefront:
        return wavefront.normalise()
FourierBasis

dLux.layers.optical_layers.FourierBasis ¤

Bases: OpticalLayer

Optical layer for representing an OPD using a 2D real Fourier basis.

UML

UML

Attributes:

Name Type Description
coefficients Array

The Fourier coefficients, ordered in (x, y) mode order.

kernels tuple[Array, Array]

The cached Fourier evaluation kernels for the x and y axes.

Source code in dLux/layers/optical_layers.py
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
354
355
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
class FourierBasis(OpticalLayer):
    """
    Optical layer for representing an OPD using a 2D real Fourier basis.

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

    Attributes
    ----------
    coefficients : Array
        The Fourier coefficients, ordered in `(x, y)` mode order.
    kernels : tuple[Array, Array]
        The cached Fourier evaluation kernels for the x and y axes.
    """

    coefficients: Array
    kernels: tuple[Array, Array]

    def __init__(
        self: FourierBasis,
        npix: int | tuple[int, int],
        n_modes: int | tuple[int, int],
        coefficients: Array = None,
        **kwargs,
    ):
        """
        Parameters
        ----------
        npix : int | tuple[int, int]
            The output number of pixels in `(x, y)` order.
        n_modes : int | tuple[int, int]
            The number of Fourier modes in `(x, y)` order.
        coefficients : Array = None
            The Fourier coefficients. Defaults to zeros if not provided.
        """
        self.kernels = dlu.fourier_kernels(n_modes, npix)
        coefficient_shape = tuple(kernel.shape[1] for kernel in self.kernels)

        if coefficients is None:
            coefficients = np.zeros(coefficient_shape)
        else:
            coefficients = np.asarray(coefficients, dtype=float)
            if coefficients.shape != coefficient_shape:
                raise ValueError(
                    "The Fourier coefficient array must match the number of "
                    "modes in each dimension."
                )

        self.coefficients = coefficients
        super().__init__(**kwargs)

    def update_kernels(self: FourierBasis, npix: int | tuple[int, int]) -> FourierBasis:
        """
        Returns a copy of the layer with kernels updated for a new output size.

        Parameters
        ----------
        npix : int | tuple[int, int]
            The updated output number of pixels in `(x, y)` order.

        Returns
        -------
        layer : FourierBasis
            A copy of the layer with updated Fourier kernels.
        """
        kernels = dlu.fourier_kernels(self.coefficients.shape, npix)
        return self.set(kernels=kernels)

    def eval_basis(self: FourierBasis) -> Array:
        """
        Evaluates the Fourier basis represented by the current coefficients.

        Returns
        -------
        output : Array
            The evaluated Fourier basis.
        """
        return dlu.eval_fourier_basis(self.coefficients, *self.kernels)

    def __call__(self: FourierBasis, wavefront: Wavefront) -> Wavefront:
        """
        Applies the evaluated Fourier basis to the input wavefront as an OPD.

        Parameters
        ----------
        wavefront : Wavefront
            The input wavefront.

        Returns
        -------
        wavefront : Wavefront
            The wavefront with the Fourier basis applied as an OPD.
        """
        return wavefront.add_opd(self.eval_basis())

__call__(wavefront) ¤

Applies the evaluated Fourier basis to the input wavefront as an OPD.

Parameters:

Name Type Description Default
wavefront Wavefront

The input wavefront.

required

Returns:

Name Type Description
wavefront Wavefront

The wavefront with the Fourier basis applied as an OPD.

Source code in dLux/layers/optical_layers.py
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
def __call__(self: FourierBasis, wavefront: Wavefront) -> Wavefront:
    """
    Applies the evaluated Fourier basis to the input wavefront as an OPD.

    Parameters
    ----------
    wavefront : Wavefront
        The input wavefront.

    Returns
    -------
    wavefront : Wavefront
        The wavefront with the Fourier basis applied as an OPD.
    """
    return wavefront.add_opd(self.eval_basis())

__init__(npix, n_modes, coefficients=None, **kwargs) ¤

Parameters:

Name Type Description Default
npix int | tuple[int, int]

The output number of pixels in (x, y) order.

required
n_modes int | tuple[int, int]

The number of Fourier modes in (x, y) order.

required
coefficients Array = None

The Fourier coefficients. Defaults to zeros if not provided.

None
Source code in dLux/layers/optical_layers.py
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
def __init__(
    self: FourierBasis,
    npix: int | tuple[int, int],
    n_modes: int | tuple[int, int],
    coefficients: Array = None,
    **kwargs,
):
    """
    Parameters
    ----------
    npix : int | tuple[int, int]
        The output number of pixels in `(x, y)` order.
    n_modes : int | tuple[int, int]
        The number of Fourier modes in `(x, y)` order.
    coefficients : Array = None
        The Fourier coefficients. Defaults to zeros if not provided.
    """
    self.kernels = dlu.fourier_kernels(n_modes, npix)
    coefficient_shape = tuple(kernel.shape[1] for kernel in self.kernels)

    if coefficients is None:
        coefficients = np.zeros(coefficient_shape)
    else:
        coefficients = np.asarray(coefficients, dtype=float)
        if coefficients.shape != coefficient_shape:
            raise ValueError(
                "The Fourier coefficient array must match the number of "
                "modes in each dimension."
            )

    self.coefficients = coefficients
    super().__init__(**kwargs)

eval_basis() ¤

Evaluates the Fourier basis represented by the current coefficients.

Returns:

Name Type Description
output Array

The evaluated Fourier basis.

Source code in dLux/layers/optical_layers.py
386
387
388
389
390
391
392
393
394
395
def eval_basis(self: FourierBasis) -> Array:
    """
    Evaluates the Fourier basis represented by the current coefficients.

    Returns
    -------
    output : Array
        The evaluated Fourier basis.
    """
    return dlu.eval_fourier_basis(self.coefficients, *self.kernels)

update_kernels(npix) ¤

Returns a copy of the layer with kernels updated for a new output size.

Parameters:

Name Type Description Default
npix int | tuple[int, int]

The updated output number of pixels in (x, y) order.

required

Returns:

Name Type Description
layer FourierBasis

A copy of the layer with updated Fourier kernels.

Source code in dLux/layers/optical_layers.py
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
def update_kernels(self: FourierBasis, npix: int | tuple[int, int]) -> FourierBasis:
    """
    Returns a copy of the layer with kernels updated for a new output size.

    Parameters
    ----------
    npix : int | tuple[int, int]
        The updated output number of pixels in `(x, y)` order.

    Returns
    -------
    layer : FourierBasis
        A copy of the layer with updated Fourier kernels.
    """
    kernels = dlu.fourier_kernels(self.coefficients.shape, npix)
    return self.set(kernels=kernels)