Input and Output Domains
Since version 0.8.0, nrefocus.refocus(), nrefocus.refocus_stack(),
and all Refocus subclasses accept input_domain and
output_domain keyword arguments that control whether the field is
transformed to/from the Fourier domain inside nrefocus or whether the user
manages those transforms themselves.
This is useful when the field is already in Fourier space (e.g. it comes directly from a hologram reconstruction library) or when only the propagated Fourier coefficients are needed (e.g. as input to a further processing step), avoiding redundant transforms.
Note
When input_domain="fourier", the field must be provided in the
fftshifted convention (DC at the centre of the array, as returned by
numpy.fft.fftshift()). When output_domain="fourier", the result
is also returned fftshifted.
Default: spatial input, spatial output
The default behaviour applies a forward FFT to the input, multiplies by the propagation kernel, then applies the inverse FFT.
import numpy as np
import nrefocus
ny, nx = 128, 96
field = (np.random.randn(ny, nx) + 1j * np.random.randn(ny, nx)
).astype(np.complex128)
pixel_size = 1e-6
refocused = nrefocus.refocus(
field=field,
d=2.13,
nm=1.533,
res=8.25,
method="helmholtz",
padding=False,
)
print(refocused.shape) # (128, 96)
Fourier input: skip the forward FFT
If the field is already available as an fftshifted FFT, pass it with
input_domain="fourier" to skip the forward transform inside nrefocus.
import numpy as np
import nrefocus
ny, nx = 128, 96
field = (np.random.randn(ny, nx) + 1j * np.random.randn(ny, nx)
).astype(np.complex128)
# pre-compute the fftshifted FFT once
fft_field = np.fft.fftshift(np.fft.fft2(field))
pixel_size = 1e-6
refocused = nrefocus.refocus(
field=fft_field,
d=2.13,
nm=1.533,
res=8.25,
method="helmholtz",
padding=False,
input_domain="fourier",
)
print(refocused.shape) # (128, 96)
Fourier output: skip the inverse FFT
If only the propagated Fourier coefficients are needed, use
output_domain="fourier" to skip the inverse transform. The result is
returned fftshifted; apply numpy.fft.ifft2() after
numpy.fft.ifftshift() to recover the spatial field.
import numpy as np
import nrefocus
ny, nx = 128, 96
field = (np.random.randn(ny, nx) + 1j * np.random.randn(ny, nx)
).astype(np.complex128)
pixel_size = 1e-6
propagated_fft = nrefocus.refocus(
field=field,
d=2.13,
nm=1.533,
res=8.25,
method="helmholtz",
padding=False,
output_domain="fourier",
)
# propagated_fft is fftshifted; recover the spatial field manually
refocused = np.fft.ifft2(np.fft.ifftshift(propagated_fft))
print(refocused.shape) # (128, 96)
Combining both: no transforms at all
Setting both input_domain="fourier" and output_domain="fourier"
reduces the pipeline to a single kernel multiplication — no FFT or iFFT is
performed inside nrefocus.
propagated_fft = nrefocus.refocus(
field=fft_field, # already fftshifted
d=2.13,
nm=1.533,
res=8.25,
method="helmholtz",
padding=False,
input_domain="fourier",
output_domain="fourier",
)
For a complete working example see the Examples.