slmsuite.hardware.slms.meadowlark.Meadowlark#
- class Meadowlark(verbose=True, sdk_path='C:\\Program Files\\Meadowlark Optics\\Blink 1920 HDMI\\', lut_path=None, wav_um=1, pitch_um=(8, 8), **kwargs)[source]#
Bases:
SLMInterfaces with Meadowlark SLMs.
- slm_lib#
Connection to the Meadowlark library.
- Type:
ctypes.CDLL
- sdk_path#
Path of the Blink SDK folder.
- Type:
str
Methods
See
SLM.close().Extracts various
sourceparameters from the source for use in analytic functions.Read the voltage of the SLM coverglass.
Fourier transforms the wavefront calibration's measured amplitude to find the expected diffraction-limited performance of the system in
"knm"space.Extracts the scaling for
zernike_aperture()from the scalars computed infit_source_amplitude().Extracts the source radius in normalized units for functions like
laguerre_gaussian()from the scalars computed infit_source_amplitude().Extracts the scaling for
zernike_aperture()from the scalars computed infit_source_amplitude().Approximates the expected standard deviation radius of farfield spots in the
"kxy"basis based on the near-field amplitude distribution stored insource.Read the temperature of the SLM.
The normal behavior of this function is to discover the names of all the displays to help the user identify the correct display.
Loads a voltage 'look-up table' (LUT) to the SLM.
Loads
displayfrom a file and writes to the SLM.Loads vendor-provided phase correction from file, setting
source["phase"].Returns a dictionary containing selected attributes of this class.
Plots the provided phase.
Plots measured or simulated amplitude and phase distribution of the SLM illumination.
Saves the dictionary returned from
pickle()to a file like"path/name_id.h5".Checks, cleans, and adds to data, then sends the data to the SLM and potentially waits for settle.
In the absence of a proper wavefront calibration, sets
sourceamplitude and phase using a fit_function fromfitfunctions.Backwards-compatibility alias for
set_phase().- __init__(verbose=True, sdk_path='C:\\Program Files\\Meadowlark Optics\\Blink 1920 HDMI\\', lut_path=None, wav_um=1, pitch_um=(8, 8), **kwargs)[source]#
Initializes an instance of a Meadowlark SLM.
Caution
Meadowlarkdefaults to 8 micron SLM pixel size. This is valid for most Meadowlark models, but not true for all!- Parameters:
verbose (bool) – Whether to print extra information.
sdk_path (str) –
Path of the Blink SDK installation folder. Stored in
sdk_path.Important
If the installation is not in the default folder, then this path needs to be corrected.
lut_path (str OR None) –
Passed to
load_lut(). Looks for the voltage ‘look-up table’ data which is necessary to run the SLM.Tip
See
load_lut()for how the default argument and other options are parsed.wav_um (float) – Wavelength of operation in microns. Defaults to 1 um.
pitch_um ((float, float)) – Pixel pitch in microns. Defaults to 8 micron square pixels.
**kwargs – See
SLM.__init__()for permissible options.
- load_lut(lut_path=None)[source]#
Loads a voltage ‘look-up table’ (LUT) to the SLM. This converts requested phase values to physical voltage perturbing the liquid crystals.
- Parameters:
lut_path (str OR None) –
Path to look for an LUT file in.
If this is a .lut file, then this file is loaded to the SLM.
If this is a directory, then searches all files inside the directory, and loads either the alphabetically-first .lut file or if possible the alphabetically-first .lut file starting with
"slm"which is more likely to correspond to the LUT customized to an SLM, as Meadowlark sends such files prefixed by"slm"such as"slm5758_at532.lut".
- Raises:
RuntimeError – If a .lut file is not found.
- Returns:
The path which was used to load the LUT.
- Return type:
str
- static info(verbose=True)[source]#
The normal behavior of this function is to discover the names of all the displays to help the user identify the correct display. However, Meadowlark software does not currently support multiple SLMs, so this function instead raises an error.
- Parameters:
verbose (bool) – Whether to print the discovered information.
- Raises:
NotImplementedError –
- close()[source]#
See
SLM.close().
- get_temperature()[source]#
Read the temperature of the SLM.
- Returns:
Temperature in degrees celcius.
- Return type:
float
- get_coverglass_voltage()[source]#
Read the voltage of the SLM coverglass.
- Returns:
Voltage of the SLM coverglass.
- Return type:
float
- fit_source_amplitude(method='moments', extent_threshold=0.1, force=True)[source]#
Extracts various
sourceparameters from the source for use in analytic functions. This is done by analyzing thesource["amplitude"]distribution with"moments"or least squares"fit". These parameters include the following keys:"amplitude_center_pix": (float, float)Pixel corresponding to the center of the source. The grid is also changed to be centered on this pixel.
"amplitude_radius": floatThe radial standard deviation of the amplitude distribution in normalized units. For a Gaussian source, this is the \(1/e\) amplitude radius (\(1/e^2\) power radius). This is scalar and averages the \(x\) and \(y\) distributions. This is used to set the source radius for
laguerre_gaussian()and similar."amplitude_extent": (float, float)The box radii of the smallest rectangle which covers all amplitude larger than
extent_threshold, where the maximum of the distribution is normalized to one."amplitude_extent_radius": floatSmallest scalar radius about the center of the that covers all amplitude larger than
extent_threshold, where the maximum of the distribution is normalized to one. This is used to determine the scaling forzernike_aperture(): Too small of a scaling is not good because amplitude would overlap outside where Zernike is defined, with divergent phase for higher order Zernike polynomials. Too large of a scaling is not good because one needs to use high order Zernike to attain sufficient spatial resolution at the center of the distribution.
Important
If
source["amplitude"]is not set, then the parameters are guessed as fractions of the grid:"amplitude_center_pix"Unchanged from current center."amplitude_radius"Guessed as 1/4 of the smallest extent."amplitude_extent"Guessed as the the rectangle that circumscribes the SLM field."amplitude_extent_radius"Guessed as the the radius that circumscribes the SLM field.
Important
The
gridis recentered upon the detected center of the source. Thisgridis used to generated phase functions likelens()orlaguerre_gaussian(). Such generation works best when centered upon the source; alens()focuses coaxially and alaguerre_gaussian()appears symmetric.- Parameters:
method (str {"fit", "moments"}) – Whether to use moment calculations
"moments"or a least squares"fit"to determine"amplitude_center_pix"and"amplitude_radius"."moments"is faster but"fit"is more accurate.extent_threshold (float) – Fraction of the maximal amplitude to use as the full extent of the amplitude distribution.
force (bool) – If
False, does not calculate if these quantities already exist.Trueforces recomputation.
- get_point_spread_function_knm(padded_shape=None)[source]#
Fourier transforms the wavefront calibration’s measured amplitude to find the expected diffraction-limited performance of the system in
"knm"space.- Parameters:
padded_shape ((int, int) OR None) – The point spread function changes in resolution depending on the padding. Use this variable to provide this padding. If
None, do not pad.- Returns:
The point spread function of shape
padded_shape.- Return type:
numpy.ndarray
- get_source_center()[source]#
Extracts the scaling for
zernike_aperture()from the scalars computed infit_source_amplitude().
- get_source_radius()[source]#
Extracts the source radius in normalized units for functions like
laguerre_gaussian()from the scalars computed infit_source_amplitude().
- get_source_zernike_scaling()[source]#
Extracts the scaling for
zernike_aperture()from the scalars computed infit_source_amplitude().
- get_spot_radius_kxy()[source]#
Approximates the expected standard deviation radius of farfield spots in the
"kxy"basis based on the near-field amplitude distribution stored insource. For a Gaussian source, this is the \(1/e\) amplitude radius (\(1/e^2\) power radius).- Returns:
Radius of the farfield spot.
- Return type:
float
- load_phase(file_path=None, settle=False)[source]#
Loads
displayfrom a file and writes to the SLM.- Parameters:
file_path (str OR None) – Full path to the phase file. If
None, will search the current directory for a file with a name likename+'-phase'.settle (bool) – Whether to sleep for
settle_time_s.
- Returns:
The file path that the phase was loaded from.
- Return type:
str
- Raises:
FileNotFoundError – If a file is not found.
Warning – Warns the user if the stored
phasedoes not agree with the displayed value.
- load_vendor_phase_correction(file_path)[source]#
Loads vendor-provided phase correction from file, setting
source["phase"]. By default, this is interpreted as an image file and is padded or unpadded to the shape of the SLM. Subclasses should implement vendor-specific routines for loading and interpreting the file (e.g.Santecloads a .csv).- Parameters:
file_path (str) – File path for the vendor-provided phase correction.
- Returns:
source["phase"], the vendor-provided phase correction.- Return type:
numpy.ndarray
- pickle(attributes=True, metadata=True)[source]#
Returns a dictionary containing selected attributes of this class.
- Parameters:
attributes (bool OR list of str) – If
False, pickles only baseline attributes, usually single floats. IfTrue, also pickles ‘heavy’ attributes such as large images and calibrations. Iflist of str, pickles the keys in the given list. By default, the chosen attributes should be things that can be written to .h5 files: scalars and lists of scalars.metadata (bool) – If
True, package the dictionary as the"__meta__"value of a superdictionary which also contains:"__version__", the current slmsuite version,"__time__", the time formatted as a date string, and"__timestamp__", the time formatting as a floating point timestamp. This information is used as standard metadata for calibrations and saving.
- plot(phase=None, limits=None, title='Phase', ax=None, cbar=True)[source]#
Plots the provided phase.
- Parameters:
phase (ndarray OR None) – Phase to be plotted. If
None, grabs the last writtenphasefrom the SLM.limits (None OR float OR [[float, float], [float, float]]) – Scales the limits by a given factor or uses the passed limits directly.
title (str) – Title the axis.
ax (matplotlib.pyplot.axis OR None) – Axis to plot upon.
cbar (bool) – Also plot a colorbar.
- Returns:
Axis of the plotted phase.
- Return type:
matplotlib.pyplot.axis
- plot_source(sim=False, power=False)[source]#
Plots measured or simulated amplitude and phase distribution of the SLM illumination. Also plots the rsquared goodness of fit value if available.
- Parameters:
sim (bool) – Plots the simulated source distribution if
Trueor the measured source distribution ifFalse.power (bool) – If
True, plot the power (amplitude squared) instead of the amplitude.
- Returns:
Axis handles for the generated plot.
- Return type:
matplotlib.pyplot.axis
- save(path='.', name=None, **kwargs)[source]#
Saves the dictionary returned from
pickle()to a file like"path/name_id.h5".- Parameters:
path (str) – Path to directory to save in. Default is current directory.
name (str OR None) – Name of the save file. If
None, will usename+'-pickle'.**kwargs – Passed to
pickle()to customize how and what data is saved.
- Returns:
The file path that the pickled data was saved to.
- Return type:
str
- save_phase(path='.', name=None)[source]#
Saves
phaseanddisplayto a file like"path/name_id.h5".- Parameters:
path (str) – Path to directory to save in. Default is current directory.
name (str OR None) – Name of the save file. If
None, will usename+'-phase'.
- Returns:
The file path that the phase was saved to.
- Return type:
str
- set_phase(phase, phase_correct=True, settle=False)[source]#
Checks, cleans, and adds to data, then sends the data to the SLM and potentially waits for settle. This method calls the SLM-specific private method
_set_phase_hw()which transfers the data to the SLM.Warning
Subclasses implementing vendor-specific software should not overwrite this method. Subclasses should overwrite
_set_phase_hw()instead.Caution
The sign on
phaseis flipped before converting to integer data. This is to convert between the ‘increasing value ==> increasing voltage (= decreasing phase delay)’ convention in most SLMs andslmsuite’s ‘increasing value ==> increasing phase delay’ convention. As a result, zero phase will appear entirely white (255 for an 8-bit SLM), and increasing phase will darken the displayed pattern. If integer data is passed, this data is displayed directly and the sign is not flipped.Important
The user does not need to wrap (e.g.
numpy.mod(data, 2*numpy.pi)) the passed phase data, unless they are pre-caching data for speed (see below).set_phase()uses optimized routines to wrap the phase (see the private method_phase2gray()). Which routine is used depends onphase_scaling:phase_scalingis one.Fast bitwise integer modulo is used. Much faster than the other routines which depend on
numpy.mod().
phase_scalingis less than one.In this case, the SLM has more phase tuning range than necessary. If the data is within the SLM range
[0, 2*pi/phase_scaling], then the data is passed directly. Otherwise, the data is wrapped by \(2\pi\) using the very slownumpy.mod(). Try to avoid this in applications where speed is important.
phase_scalingis more than one.In this case, the SLM has less phase tuning range than necessary. Processed the same way as the
phase_scalingis less than one case, with the important exception that phases (after wrapping) between2*pi/phase_scalingand2*piare set to zero. For instance, a sawtooth blaze would be truncated at the tips.
Caution
After scale conversion, data is
floor()ed to integers withnp.copyto, rather than rounded to the nearest integer (np.rint()equivalent). While this is irrelevant for the average user, it may be significant in some cases. If this behavior is undesired consider either:set_phase()integer data directly or modifying the behavior of the private method_phase2gray()in a pull request. We have not been able to find an example ofnp.copytoproducing undesired behavior, but will change this if such behavior is found.- Parameters:
phase (numpy.ndarray OR slmsuite.holography.algorithms.Hologram OR None) –
Phase data to display in units of \(2\pi\), unless the passed data is of integer type and the data is applied directly.
If
Noneis passed toset_phase(), data is zeroed.If a
Hologramis passed, the phase is grabbed fromget_phase().If the array has a larger shape than the SLM shape, then the data is cropped to size in a centered manner (
unpad).If integer data is passed with the same type as
display(np.uint8for <=8-bit SLMs,np.uint16otherwise), then this data is directly passed to the SLM, without going through the “phase delay to grayscale” conversion defined in the private method_phase2gray(). In this situation,phase_correctis ignored. This is error-checked such that bits with greater significance than the bitdepth of the SLM are zero (e.g. the final 6 bits of 16 bit data for a 10-bit SLM). Integer data with type different fromdisplayleads to a TypeError.
Usually, an exact stored copy of the data passed by the user under
phaseis stored in the attributephase. However, in cases wherephase_scalingnot one, this copy is modified to include how the data was wrapped. If the data was cropped, then the cropped data is stored, etc. If integer data was passed, the equivalent floating point phase is computed and stored in the attributephase.phase_correct (bool) – Whether or not to add
source```["phase"]`tophase.settle (bool) – Whether to sleep for
settle_time_s.
- Returns:
display, the integer data sent to the SLM.- Return type:
numpy.ndarray
- Raises:
TypeError – If integer data is incompatible with the bitdepth or if the passed phase is otherwise incompatible (not a 2D array or smaller than the SLM shape, etc).
- set_source_analytic(fit_function='gaussian2d', units='norm', phase_offset=0, sim=False, **kwargs)[source]#
In the absence of a proper wavefront calibration, sets
sourceamplitude and phase using a fit_function fromfitfunctions.Note
FourierSLMincludes capabilities for wavefront calibration viawavefront_calibrate(). This process also measures the amplitude of the source on the SLM and stores this insource.sourcekeywords are also used for better refinement of holograms during numerical optimization. If unable to runwavefront_calibrate(), this method allows the user to set an approximation of the complex source.- Parameters:
fit_function (str OR lambda) – Function name from
fitfunctionsused to set the source profile. The function can also be passed directly. Defaults to"gaussian2d".units (str in {"norm", "frac", "nm", "um", "mm", "m"}) – Units for the \((x,y)\) grid passed to
fit_function. This essentially determines the scaling on the normalized grid stored in the SLM which is passed to thefit_function.sim (bool) – Sets the simulated source distribution if
Trueor the approximate experimental source distribution (in absence of wavefront calibration) ifFalse.phase_offset (float OR numpy.ndarray) – Additional phase (of shape
shape) added tosource.**kwargs – Arguments passed to
fit_functionin addition to the SLM grid in the requestedunits. If thefit_functionis"gaussian2d"and no keyword arguments have been passed, the radius defaults to 1/2 of the smaller of the two SLM dimensions.
- Returns:
- Return type:
dict
- write(phase, phase_correct=True, settle=False)[source]#
Backwards-compatibility alias for
set_phase().