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: SLM

Interfaces with Meadowlark SLMs.

slm_lib#

Connection to the Meadowlark library.

Type:

ctypes.CDLL

sdk_path#

Path of the Blink SDK folder.

Type:

str

Methods

close

See SLM.close().

fit_source_amplitude

Extracts various source parameters from the source for use in analytic functions.

get_coverglass_voltage

Read the voltage of the SLM coverglass.

get_point_spread_function_knm

Fourier transforms the wavefront calibration's measured amplitude to find the expected diffraction-limited performance of the system in "knm" space.

get_source_center

Extracts the scaling for zernike_aperture() from the scalars computed in fit_source_amplitude().

get_source_radius

Extracts the source radius in normalized units for functions like laguerre_gaussian() from the scalars computed in fit_source_amplitude().

get_source_zernike_scaling

Extracts the scaling for zernike_aperture() from the scalars computed in fit_source_amplitude().

get_spot_radius_kxy

Approximates the expected standard deviation radius of farfield spots in the "kxy" basis based on the near-field amplitude distribution stored in source.

get_temperature

Read the temperature of the SLM.

info

The normal behavior of this function is to discover the names of all the displays to help the user identify the correct display.

load_lut

Loads a voltage 'look-up table' (LUT) to the SLM.

load_phase

Loads display from a file and writes to the SLM.

load_vendor_phase_correction

Loads vendor-provided phase correction from file, setting source["phase"].

pickle

Returns a dictionary containing selected attributes of this class.

plot

Plots the provided phase.

plot_source

Plots measured or simulated amplitude and phase distribution of the SLM illumination.

save

Saves the dictionary returned from pickle() to a file like "path/name_id.h5".

save_phase

Saves phase and display to a file like "path/name_id.h5".

set_phase

Checks, cleans, and adds to data, then sends the data to the SLM and potentially waits for settle.

set_source_analytic

In the absence of a proper wavefront calibration, sets source amplitude and phase using a fit_function from fitfunctions.

write

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

Meadowlark defaults 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 source parameters from the source for use in analytic functions. This is done by analyzing the source ["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" : float

    The 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" : float

    Smallest 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 for zernike_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 grid is recentered upon the detected center of the source. This grid is used to generated phase functions like lens() or laguerre_gaussian(). Such generation works best when centered upon the source; a lens() focuses coaxially and a laguerre_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. True forces 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 in fit_source_amplitude().

get_source_radius()[source]#

Extracts the source radius in normalized units for functions like laguerre_gaussian() from the scalars computed in fit_source_amplitude().

get_source_zernike_scaling()[source]#

Extracts the scaling for zernike_aperture() from the scalars computed in fit_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 in source. 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 display from 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 like name + '-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 phase does 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. Santec loads 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. If True, also pickles ‘heavy’ attributes such as large images and calibrations. If list 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 written phase from 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 True or the measured source distribution if False.

  • 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 use name + '-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 phase and display 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 use name + '-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 phase is flipped before converting to integer data. This is to convert between the ‘increasing value ==> increasing voltage (= decreasing phase delay)’ convention in most SLMs and slmsuite’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 on phase_scaling:

  • phase_scaling is one.

    Fast bitwise integer modulo is used. Much faster than the other routines which depend on numpy.mod().

  • phase_scaling is 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 slow numpy.mod(). Try to avoid this in applications where speed is important.

  • phase_scaling is more than one.

    In this case, the SLM has less phase tuning range than necessary. Processed the same way as the phase_scaling is less than one case, with the important exception that phases (after wrapping) between 2*pi/phase_scaling and 2*pi are set to zero. For instance, a sawtooth blaze would be truncated at the tips.

Caution

After scale conversion, data is floor() ed to integers with np.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 of np.copyto producing 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 None is passed to set_phase(), data is zeroed.

    • If a Hologram is passed, the phase is grabbed from get_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.uint8 for <=8-bit SLMs, np.uint16 otherwise), 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_correct is 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 from display leads to a TypeError.

    Usually, an exact stored copy of the data passed by the user under phase is stored in the attribute phase. However, in cases where phase_scaling not 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 attribute phase.

  • phase_correct (bool) – Whether or not to add source```["phase"]` to phase.

  • 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 source amplitude and phase using a fit_function from fitfunctions.

Note

FourierSLM includes capabilities for wavefront calibration via wavefront_calibrate(). This process also measures the amplitude of the source on the SLM and stores this in source. source keywords are also used for better refinement of holograms during numerical optimization. If unable to run wavefront_calibrate(), this method allows the user to set an approximation of the complex source.

Parameters:
  • fit_function (str OR lambda) – Function name from fitfunctions used 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 the fit_function.

  • sim (bool) – Sets the simulated source distribution if True or the approximate experimental source distribution (in absence of wavefront calibration) if False.

  • phase_offset (float OR numpy.ndarray) – Additional phase (of shape shape) added to source.

  • **kwargs – Arguments passed to fit_function in addition to the SLM grid in the requested units. If the fit_function is "gaussian2d" and no keyword arguments have been passed, the radius defaults to 1/2 of the smaller of the two SLM dimensions.

Returns:

source.

Return type:

dict

write(phase, phase_correct=True, settle=False)[source]#

Backwards-compatibility alias for set_phase().