Phase Processing and Visualisation

The raw output from numerical refocusing or off-axis demodulation is a complex numpy array representing the complex field. The amplitude and phase of the field are the amplitude and angle of the complex numbers in the array, respectively, and can be extracted using pyholoscope.amp() and pyholoscope.phase().

PyHoloscope has several functions for further processing of the phase. A common requirement is to subtract a reference phase, for example acquired with nothing in the field of view. This can be done automatically when using the Holo class by providing a background hologram and setting background and relative_phase (e.g. holo.background = background_img and holo.relative_phase = True), or by setting these parameters at instantiation.

Alternatively, this can be done manually using the pyholoscope.relative_phase() function. For example, assume we have off-axis demodulated a hologram, to obtain hologram_demod, for example by using the Holo class. We then also demodulate the background image to obtain background_demod in the same way. Then:

correctedImage = pyholoscope.relative_phase(hologram_demod, background_demod)

returns a complex array with the reference phase from the background hologram subtracted. It is also possible to provide the phase maps (i.e. pyholoscope.phase(hologram_demod) and pyholoscope.phase(background_demod)) instead, in which case the corrected phase will be returned. The function assumes that the inputs are phase maps if the datatype is not complex.

Phase Unwrapping

An unwrapped phase map can be created by passing the wrapped phase map to pyholoscope.phase_unwrap(). Note that this function accepts either a phase map or the complex field, but the output unwrapped phase map is always real, i.e. the unwrapped phase cannot be represented as a complex field. The phase unwrapping uses the method shipped with skimage, based on:

Miguel Arevallilo Herraez, David R. Burton, Michael J. Lalor, and Munther A. Gdeisat, “Fast two-dimensional phase-unwrapping algorithm based on sorting by reliability following a noncontinuous path”, Journal Applied Optics, Vol. 41, No. 35, pp. 7437, 2002

Tilt Removal

The way in which a sample is mounted may lead to further distortions of the phase map that are not accounted for by subtraction of a reference phase. This often manifests as a tilt. This can be removed by first estimating the tilt from the unwrapped phase and then subtracting it, using pyholoscope.obtain_tilt() and the removing this using pyholoscope.relative_phase(). Note that pyholoscope.obtain_tilt() must be passed the unwrapped phase map, e.g. from pyholoscope.phase_unwrap(), otherwise the tilt will not be found correctly.

For example, assuming we have a complex field in hologram_demod:

unwrapped_phase = pyholoscope.phase_unwrap(hologram_demod)
tilt = pyholoscope.obtain_tilt(unwrapped_phase)
corrected_phase = pyholoscope.relative_phase(unwrapped_phase, tilt)

This returns the unwrapped and tilt-corrected phase map in corrected_phase. It is possible to use pyholoscope.relative_phase() twice, once to remove the background phase distortion due to the system (in which case the tilt should be estimated from this background-corrected phase) and then again to correct the tilt.

Phase Stabilisation

In live imaging or video recording, the global phase will tend to drift over time. To avoid this visual effect, the phase can be referenced to a part of the image which is known not to contain any object using pyholoscope.relative_phase_self(). Define a region of interest (ROI) using Roi and then pass this along with the complex field or phase map, for example:

roi = pyholoscope.Roi(x=20, y=20, w = 100, h = 100)
corrected_phase = pyholoscope.relative_phase_self(hologram_demod, roi)

Alternatively, do not pass a ROI to make the phase relative to the mean phase across the entire image. This gives good results only when the object makes up a small fraction of the image.

The function works with both the complex field and phase maps, but will not be effective when the complex field contains wrapped phase or uncorrected tilt or other distortions. It is normally best to correct these issues first using the relative phase, tilt removal and phase unwrapping functions, and then pass the unwrapped, corrected phase to pyholoscope.relative_phase_self().

Visualisation

PyHoloscope includes two functions, pyholoscope.phase_gradient() and pyholoscope.synthetic_DIC() to generate a phase gradient image and an approximation to a DIC image, respectively.

Both functions accept either the complex field or phase map (i.e. a complex or float array) and work with wrapped phase. Artefacts due to wrapping are avoided by correcting large jumps in phase. pyholoscope.phase_gradient_amp() is used internally by pyholoscope.phase_gradient(), and does not remove the wrapping (on unwrapped phase maps either functions can be used and return identical values).

A third function, pyholoscope.phase_gradient_dir() can be used to return a directional gradient map. This map is returned as a complex array, with the amplitudes being the amplitude of the gradient at each point, and the angles being the direction. This function should be provided with the unwrapped phase.

Saving Phase Maps

Wrapped phase maps can be saved to image files using pyholoscope.save_phase_image(), which saves the phase map as a 16 bit tif, in which a pixel value of 0 corresponds to a phase of 0 and a pixel values of 65535 corresponds to 2pi. The function accepts either phase maps or complex fields. If a phase map is provided, any phase values outside of the [0, 2pi] interval will be wrapped to this interval.

An unwrapped phase map, stored as a float array, can be saved using pyholoscope.save_image() or pyholoscope.save_image16(), to save as 8 or 16 bit images respectively. Note that the images will be autoscaled so that the minimum phase value is 0 and the max is either 255 or 65535, respectively. To avoid this, pass autoscale = False, in which case the phase values will be cast directly to the relevant data type, in which case it is the caller’s responsibility to ensure the range is sensible.