Interferograms

Prysm offers rich features for analysis of interferometric data. Interferogram objects are conceptually similar to Pupils and both inherit from the same base class, as they both have to do with optical phase. The construction of an Interferogram requires only a few parameters:

>>> import numpy as np
>>> from prysm import Interferogram
>>> x = y = np.arange(129)
>>> z = np.random.uniform((128,128))
>>> interf = Interferogram(phase=z, intensity=None, unit_x=x, unit_y=y, scale='mm', phase_unit='nm', meta={'wavelength': 632.8e-9})

Notable are the scale, and phase unit, which define the xy and z units, respectively. Any SI unit is accepted as well as angstroms. Imperial units not accepted. meta is a dictionary to store metadata. For several interferogram methods to work, the wavelength must be present in meters. This departure from prysm’s convention of preferred units is used to maintain compatability with Zygo dat files. Interferograms are usually created from such files:

>>> interf = Interferogram.from_zygo_dat(your_path_file_object_or_bytes)

and both the dat and datx format from Zygo are supported. Dat carries no dependencies, while datx requries the installation of h5py. In addition to properties inherited from the OpticalPhase class (pv, rms, Sa, std), Interferograms have a dropout_percentage property, which gives the percentage of NaN values within the phase array. These NaNs may be filled,

>>> interf.fill(_with=0)

with 0 as a default value; only constants are supported. The modification is done in-place and the method returns self. Piston, tip-tilt, and power may be removed:

>>> interf.fill()\
>>>     .remove_piston()\
>>>     .remove_tiptilt()\
>>>     .remove_power()

again done in-place and returning self, so methods can be chained. One line convenience wrappers exist:

>>> interf.remove_piston_tiptilt()
>>> interf.remove_piston_tiptilt_power()

spikes may also be clipped,

>>> interf.spike_clip(nsigma=3)  # default is 3

setting points with a value more than nsigma standard deviations from the mean to NaN. Masks may be applied:

>>> your_mask = np.ones(interf.phase.shape)
>>> interf.mask(your_mask)

the phase is deleted (replaced with NaN) wherever the mask is equal to zero. The same applies to the intensity.

Interferograms may be cropped, deleting empty (NaN) regions around a measurment;

>>> interf.crop()

Convenience properties are provided for data size,

>>> interf.shape, interf.diameter_x, interf.diameter_y, interf.diameter

shape mirrors the shape of the underlying ndarray. The x and y diameters are in units of interf.spatial_unit and diameter is the greater of the two.

The two dimensional Power Spectral Density (PSD) may be computed. The data may not contain NaNs, and piston tip and tilt should be removed prior. A 2D Welch window is used, so there is no need for concern about zero values creating a discontinuity at the edge of circular or other nonrectangular apertures.

>>> interf.crop().remove_piston_tiptilt_power().fill()
>>> ux, uy, psd = interf.psd()

x, y, and azimuthally averaged cuts of the PSD are also available

>>> psd_dict = interf.psd_xy_avg()
>>> ux, psd_x = psd_dict['x']
>>> uy, psd_y = psd_dict['y']
>>> ur, psd_r = psd_Dict['avg']

and the PSD may be plotted,

>>> interf.plot_psd2d(axlim=1, interp_method='lanczos', fig=None, ax=None)
>>> interf.plot_psd_xyavg(xlim=(1e0,1e3), ylim=(1e-7,1e2), fig=None, ax=None)

For the x/y and average plot, a Lorentzian model may be plotted alongside the data for e.g. visual verification of a requirement:

>>> interf.plot_psd_xyavg(a=1,b=1,c=1)

A bandlimited RMS value derived from the 2D PSD may also be evaluated,

>>> interf.bandlimited_rms(wllow=1, wlhigh=10, flow=1, fhigh=10)

only one of wavelength (wl; spatial period) or frequency (f) should be provided. f will overrule wavelength.

The complete API documentation is below.


class prysm.interferogram.Interferogram(phase, intensity=None, x=None, y=None, scale='px', phase_unit='nm', meta=None)[source]

Bases: prysm._phase.OpticalPhase

Class containing logic and data for working with interferometric data.

bandlimited_rms(wllow=None, wlhigh=None, flow=None, fhigh=None)[source]

Calculate the bandlimited RMS of a signal from its PSD.

wllow : float
short spatial scale
wlhigh : float
long spatial scale
flow : float
low frequency
fhigh : float
high frequency
float
band-limited RMS value.
crop()[source]

Crop data to rectangle bounding non-NaN region.

dropout_percentage

Percentage of pixels in the data that are invalid (NaN).

fill(_with=0)[source]

Fill invalid (NaN) values.

_with : float, optional
value to fill with
Interferogram
self
static from_zygo_dat(path, multi_intensity_action='first', scale='um')[source]

Create a new interferogram from a zygo dat file.

path : path_like
path to a zygo dat file
multi_intensity_action : str, optional
see io.read_zygo_dat
scale : str, optional, {‘um’, ‘mm’}
what xy scale to label the data with, microns or mm
Interferogram
new Interferogram instance
mask(mask)[source]

Apply a mask to the data.

mask : numpy.ndarray
masking array; expects an array of zeros (remove) and ones (keep)
Interferogram
self
plot_psd2d(axlim=None, clim=(1e-09, 100.0), interp_method='lanczos', fig=None, ax=None)[source]

Plot the two dimensional PSD.

axlim : float, optional
symmetrical axis limit
power : float, optional
inverse of power to stretch image by
interp_method : str, optional
method used to interpolate the image, passed directly to matplotlib imshow
fig : matplotlib.figure.Figure
Figure containing the plot
ax : matplotlib.axes.Axis
Axis containing the plot
fig : matplotlib.figure.Figure
Figure containing the plot
ax : matplotlib.axes.Axis
Axis containing the plot
plot_psd_xyavg(a=None, b=None, c=None, lw=3, xlim=None, ylim=None, fig=None, ax=None)[source]

Plot the x, y, and average PSD on a linear x axis.

a : float, optional
a coefficient of Lorentzian PSD model plotted alongside data
b : float, optional
b coefficient of Lorentzian PSD model plotted alongside data
c : float, optional
c coefficient of Lorentzian PSD model plotted alongside data
lw : float, optional
linewidth provided directly to matplotlib
xlim : tuple, optional
len 2 tuple of low, high x axis limits
ylim : tuple, optional
len 2 tuple of low, high y axis limits
fig : matplotlib.figure.Figure
Figure containing the plot
ax : matplotlib.axes.Axis
Axis containing the plot
fig : matplotlib.figure.Figure
Figure containing the plot
ax : matplotlib.axes.Axis
Axis containing the plot
psd()[source]

Power spectral density of the data., units (self.phase_unit^2)/((cy/self.spatial_unit)^2).

unit_x : numpy.ndarray
ordinate x frequency axis
unit_y : numpy.ndarray
ordinate y frequency axis
psd : numpy.ndarray
power spectral density
psd_xy_avg()[source]

Power spectral density of the data., units (self.phase_unit^2)/((cy/self.spatial_unit)^2).

dict
with keys x, y, avg. Each containing a tuple of (unit, psd)
remove_piston()[source]

Remove piston from the data by subtracting the mean value.

remove_piston_tiptilt()[source]

Remove piston/tip/tilt from the data, see remove_tiptilt and remove_piston.

remove_piston_tiptilt_power()[source]

Remove piston/tip/tilt/power from the data.

remove_power()[source]

Remove power from the data by least squares fitting.

remove_tiptilt()[source]

Remove tip/tilt from the data by least squares fitting and subtracting a plane.

spike_clip(nsigma=3)[source]

Clip points in the data that exceed a certain multiple of the standard deviation.

nsigma : float
number of standard deviations to keep
self
this Interferogram instance.