Inline Holography Basics
Inline Holography is performed using the Holo
class of PyHoloscope by setting mode = pyholoscope.INLINE
. This allows
numerical refocusing using the angular spectrum method, as well as optional backgroud subtraction, normalisation and windowing.
See the Holo class documentation for a full list of methods and arguments. For code examples see the Inline Holography Example
Inline Holography Advanced Example on github.
Getting Started using the Holo class
Begin by importing the PyHoloscope package:
import pyholoscope as pyh
and create an instance of the Holo
class. At a minimum we need to set the mode to inline
holography and provide the physical pixel size and the wavelength:
holo = pyh.Holo(mode = pyh.INLINE, pixelSize = 2e-6, wavelength = 0.5e-6)
The pixel size and wavelength can be in any units as long as they are the same, and subsequently the refocus depth will be in the same units.
Better quality inline holography refocusing is normally achieved if we first
subtract a background image, acquired with no object in the field-of-view.
Assuming the background image is stored in the 2D numpy array backgroundImg
,
a background can be specified using:
holo.set_background(backgroundImg)
or by passing background = backgroundImg
as an argument when creating the Holo
object.
If we would like to divide through by a flat-field image stored as a 2D numpy array flatImg
, to correct for
intensity variations, we can pass normalise = flatImg
or call
set_normalise(flatImg)
.
We can now numerically refocus a hologram hologram
, again a 2D numpy array,
using the angular spectrum method by first setting the depth to refocus to, for example:
holo.set_depth(0.005)
(or by passing depth = 0.005
when creating holo) and then calling:
refocusedImg = holo.process(hologram)
The output, refocusedImg
, is a 2D complex numpy array; we can obtain the amplitude as a 2D float numpy array using:
refocusedAmp = pyh.amplitude(refocusedIm)
Note that the first time a hologram is refocused to a particular depth the process will be slower due to the need to create a propagator for that depth. This is particularly noticable when using GPU acceleration as the propagator creation will often be the rate limiting step. Subsequent refocusing to the same depth will be faster providing no parameters are changed that force a new propagator to be created (depth, pixel size, wavelength or grid size).
If we would like to smooth the edges of the hologram, we can apply a window before refocusing by calling:
holo.set_auto_window(True)
By default the window will be a rectangular cosine window. Options for the window size and shape
are set using the set_window_shape
, set_window_radius
and set_window_thickness
methods
of Holo Class.
The angular spectrum propagator and the window are both created the first time
process
is called. If we prefer to pre-generate these, we can call:
holo.update_propagator()
holo_update_auto_window()
Numba JIT acceleration
If the Numba package is installed, this will be employed for faster generation
of propagators by default when using the Holo
class. Use of Numba can be
explicitly enabled/disabled using:
holo.set_numba(True/False)
If using the lower-level functions, the Numba variant of the propagator generator function must be called explicitly:
pyh.propagator_numba(gridSize, wavelength, pixelSize, depth)
GPU acceleration
GPU acceleration is used by default when using the Holo
class, it can be
explictly enabled/disabled using:
holo.set_cuda(True/False)
This requires the CuPy package and a compatible GPU, otherwise Holo
will
revert to CPU processing.
If using the lower-level functions, it is necessary to specify cuda = True
when refocusing, e.g.:
holo.refocus(hologram, propagator, cuda = True)
Getting Started Using Lower-Level Functions
As an alternative to using the Holo
class, low-level functions can be called directly. Begin by importing the library:
import pyholoscope as pyh
Before we can refocus we define a propagator. This requires specification of the hologram size, wavelength, pixel size and the depth we wish to refocus to:
gridSize = 1024
wavelength = 0.5e-6
pixelSize = 2e-6
depth = 1e-3
prop = pyh.propagator(gridSize, wavelength, pixelSize, depth)
Assuming we have an inline hologram as a 2D numpy array hologram
we can then refocus using:
refocusedImg = pyh.refocus(hologram, propagator, background = backgroundImg)
Here we have also provided an optional background hologram, backgroundImg
, again a 2D numpy array.
The returned image is a 2D complex numpy array, to obtain the amplitude image as 2D numpy array use:
refocusedAmp = pyh.amplitude(refocusedAmp)