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
.
If the data did not have a lateral calibration baked into it, you can provide one in prysm,
>>> i.latcal(plate_scale=0.1, unit='mm')
>>> i.latcal(0.1, 'mm') # these two invocations are equal
Masks may be applied:
>>> your_mask = np.ones(interf.phase.shape)
>>> interf.mask(your_mask)
>>> interf.mask('circle', diameter=100) # 100 <spatial_unit> diameter circle
>>> interf.mask('hexagon', diameter=5)
The truecircle mask should not be used on interferometric data. the phase is deleted (replaced with NaN) wherever the mask is equal to zero.
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, interf.semidiameter
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.
-
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='mm')[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
-
latcal
(plate_scale, unit='mm')[source]¶ Perform lateral calibration.
This probably won’t do what you want if your data already has spatial units of anything but pixels (px).
- plate_scale : float
- center-to-center sample spacing of pixels, in (unit)s.
- unit : str, optional
- unit associated with the plate scale.
- self
- modified Interferogram instance.
-
mask
(shape=None, diameter=0, mask=None)[source]¶ Mask the signal.
The mask will be inscribed in the axis with fewer pixels. I.e., for a interferogram with 1280x1000 pixels, the mask will be 1000x1000 at largest.
- shape : str
- valid shape from prysm.geometry
- diameter : float
- diameter of the mask, in self.spatial_units
- mask : numpy.ndarray
- user-provided mask
- self
- modified Interferogram instance.
-
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_xy_avg
(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
if a, b given but not c, an AB / inverse power model will be used for the PSD. If a, b, c are given the Lorentzian model will be used.
-
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)
-
pvr
¶ Peak-to-Valley residual.
See: C. Evans, “Robust Estimation of PV for Optical Surface Specification and Testing” in Optical Fabrication and Testing, OSA Technical Digest (CD) (Optical Society of America, 2008), paper OWA4. http://www.opticsinfobase.org/abstract.cfm?URI=OFT-2008-OWA4
-
remove_piston_tiptilt
()[source]¶ Remove piston/tip/tilt from the data, see remove_tiptilt and remove_piston.
-
remove_tiptilt
()[source]¶ Remove tip/tilt from the data by least squares fitting and subtracting a plane.
-