Inline Holography Using Holo Class

Inline Holography can be performed using the Holo Class of PyHoloscope by setting mode = pyholoscope.INLINE. This allows numerical refocusing using the angular spectrum or Fresnel propagator methods, as well as optional background subtraction, normalisation, windowing and autofocusing. See the Holo class documentation for a full list of methods and arguments. For code examples see the Inline Holography Example or Inline Holography Advanced Example on github.

Alternatively, for more customisability, the low-level functions can be used directly as described in Inline Holography Using Lower-Level Functions .

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, pixel_size = 2e-6, wavelength = 0.5e-6)

The pixel size and wavelength should be specified in the same units (e.g. metres). Subsequently, the refocus depth should be specified in the same units.

Better quality inline holography refocusing can be achieved if we first subtract a background image, acquired with no object in the field-of-view, forming what is known as a contrast hologram. Assuming the background image is stored in the 2D numpy array background_img, a background can be specified using:

holo.background = background_img

or by passing background = background_img as an argument when creating the Holo object:

holo = pyh.Holo(mode = pyh.INLINE, pixel_size = 2e-6, wavelength = 0.5e-6, background = background_img)

If we would like to divide through by a flat-field image stored as a 2D numpy array flat_img, to correct for intensity variations, we can pass normalise = flat_img or call holo.normalise = flat_img.

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.depth = 0.005

(or by passing depth = 0.005 when instantiating Holo) and then calling:

refocused_img = holo.process(hologram)

The output, refocused_img, is a 2D complex numpy array; we can obtain the amplitude as a 2D float numpy array using:

refocused_amp = pyh.amp(refocused_img)

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 noticeable 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).

The angular spectrum propagator and the window are both created the first time process is called for a particular set of parameters. If we prefer to pre-generate these, we can call:

holo.update_propagator(img)
holo.update_auto_window(img)

where img is a 2D numpy array of the size of the hologram to be processed.

Windowing

If we would like to smooth the edges of the hologram, we can apply a window before refocusing by calling:

holo.auto_window = True

By default the window will be a rectangular cosine window. Options for the window size and shape are set using the window_shape, window_radius and window_thickness attributes of Holo Class.

Propagation Models and Geometric Magnification Correction

If required, the wavefront propagation model can be switched by changing propagation_method from "angular_spectrum" (default) to "fresnel". For example:

holo.propagation_method = "fresnel"

While less accurate than the angular spectrum method in some cases, the Fresnel method is slightly faster to compute and may be sufficient for many applications.

When using a point source, the effective pixel size is not the physical pixel camera size, as the hologram is magnified onto the camera due to projection effects. The depth value for which focus is achieved will therefore not be the true distane to the sample plane.

Effective-magnification correction can be enabled by setting correct_pixel_size = True and providing source_distance (source-to-camera distance), for example:

holo = pyh.Holo(mode = pyh.INLINE, pixel_size = 2e-6, wavelength = 0.5e-6, depth = 0.005,
                source_distance = 0.01, correct_pixel_size = True)

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.use_numba = True/False

GPU acceleration

GPU acceleration is used by default when using the Holo class, it can be explicitly enabled/disabled using:

holo.cuda = True/False

This requires the CuPy package and a compatible GPU, otherwise Holo will revert to CPU processing.