slmsuite.hardware.slms.slm.SLM
- class SLM(width, height, bitdepth=8, name='SLM', wav_um=1, wav_design_um=None, dx_um=1, dy_um=1, settle_time_s=0.3)[source]
Bases:
object
Abstract class for SLMs.
- name
Name of the SLM.
- Type
str
- shape
Stores
(height, width)
of the SLM in pixels, the same convention asnumpy.ndarray.shape
.- Type
(int, int)
- wav_um
Operating wavelength targeted by the SLM in microns. Defaults to 780 nm.
- Type
float
- wav_design_um
Design wavelength for which the maximum settable value corresponds to a \(2\pi\) phase shift. Defaults to
wav_um
if passedNone
.Tip
wav_design_um
is useful for using, for instance, an SLM designed at 1064 nm for an application at 780 nm by using only a fraction (780/1064) of the full dynamic range. It is especially useful for SLMs which do not have builtin capability to change their voltage lookup tables (e.g. Thorlabs). Even so, the max lookup wavelength (wav_design_um
) could be set larger thanwav_um
should the user want to have a phase range larger than \(2\pi\), for SLMs with lookup table capability.- Type
float
- phase_scaling
Wavelength normalized to the phase range of the SLM. See
wav_design_um
. Determined byphase_scaling = wav_um / wav_design_um
.- Type
float
- bitdepth
Depth of SLM pixel well in bits. This is useful for converting the floats which the user provides to the
bitdepth
-bit ints that the SLM reads (see the private method_phase2gray()
).- Type
int
- bitresolution
Stores
2 ** bitdepth
.- Type
int
- settle_time_s
Delay in seconds to allow the SLM to settle. This is mostly useful for applications requiring high precision. This delay is applied if the user flags
settle
inwrite()
. Defaults to .3 sec for precision.- Type
float
- dx_um
x pixel pitch in um.
- Type
float
- dx
Normalized x pixel pitch
dx_um / wav_um
.- Type
float
- x_grid
Coordinates of the SLM’s pixels in wavelengths (see
wav_um
,dx
,dy
) measured from the center of the SLM. Of sizeshape
. Produced bynumpy.meshgrid()
.- Type
numpy.ndarray<float> (height, width)
- measured_amplitude
Amplitude measured on the SLM via
wavefront_calibrate()
. Of sizeshape
. Also seeset_measured_amplitude_analytic()
to setmeasured_amplitude
without wavefront calibration. Defaults toNone
when no correction is provided.- Type
numpy.ndarray or None
- phase_correction
Phase correction devised for the SLM by
wavefront_calibrate()
. Of sizeshape
. Defaults toNone
when no correction is provided.- Type
numpy.ndarray or None
- phase
Displayed data in units of phase delay (normalized).
- Type
numpy.ndarray
- display
Displayed data in SLM units (integers).
- Type
numpy.ndarray
Methods
Abstract method to close the SLM and delete related objects.
Abstract method to load display information.
Loads vendor-provided phase correction from file, setting
phase_correction
.Fourier transforms the wavefront calibration's measured amplitude to find the expected diffraction-limited perfomance of the system in
"knm"
space.Sets
measured_amplitude
used for hologram generation in the absence of a proper wavefront calibration.Approximates the expected radius of farfield spots in the
"kxy"
basis based on the near-field amplitude distributionmeasured_amplitude
.Checks, cleans, and adds to data, then sends the data to the SLM and potentially waits for settle.
- __init__(width, height, bitdepth=8, name='SLM', wav_um=1, wav_design_um=None, dx_um=1, dy_um=1, settle_time_s=0.3)[source]
Initialize SLM.
- Parameters
width – See
shape
.height – See
shape
.bitdepth – See
bitdepth
. Defaults to 8.name – See
name
.wav_um – See
wav_um
.wav_design_um – See
wav_design_um
.dx_um – See
dx_um
.dy_um – See
dy_um
.settle_time_s – See
settle_time_s
.
- static info(verbose=True)[source]
Abstract method to load display information.
- Parameters
verbose (bool) – Whether or not to print display information.
- Returns
An empty list.
- Return type
list
- load_vendor_phase_correction(file_path)[source]
Loads vendor-provided phase correction from file, setting
phase_correction
. 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
phase_correction
, the vendor-provided phase correction.- Return type
numpy.ndarray
- write(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
_write_hw()
which transfers the data to the SLM.Warning
Subclasses implementing vendor-specific software should not overwrite this method. Subclasses should overwrite
_write_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 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).write()
uses optimized routines to wrap the phase (see the private method_phase2gray()
). Which routine is used depends onphase_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 slownumpy.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) between2*pi/phase_scaling
and2*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 withnp.copyto
, rather than rounded to the nearest integer (np.around()
equivalent). While this is irrelevant for the average user, it may be significant in some cases. If this behavior is undesired consider either:write()
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.copyto
producing undesired behavior, but will change this if such behavior is found.- Parameters
phase (numpy.ndarray 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 towrite()
, data is zeroed.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 fromdisplay
leads to a TypeError.
Usually, an exact stored copy of the data passed by the user under
phase
is stored in the attributephase
. However, in cases wherephase_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 attributephase
.phase_correct (bool) – Whether or not to add
phase_correction
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_measured_amplitude_analytic(radius, units='norm')[source]
Sets
measured_amplitude
used for hologram generation in the absence of a proper wavefront calibration.FourierSLM
includes capabilities for wavefront calibration viawavefront_calibrate()
. This process also measures the amplitude of the source on the SLM and stores this inmeasured_amplitude
.measured_amplitude
is used for better refinement of holograms during numerical optimization. If one does not have a camera to use forwavefront_calibrate()
, this method allows the user to set an approximation of the source amplitude based on an assumed \(1/e\) amplitude (\(1/e^2\) power) Gaussian beam radius.- Parameters
radius (float) – Radius in normalized units to assume for the source Gaussian beam.
units (str in {"norm", "nm", "um", "mm", "m"}) – Units for the given radius.
- Returns
- Return type
numpy.ndarray
- point_spread_function_knm(padded_shape=None)[source]
Fourier transforms the wavefront calibration’s measured amplitude to find the expected diffraction-limited perfomance 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
- spot_radius_kxy()[source]
Approximates the expected radius of farfield spots in the
"kxy"
basis based on the near-field amplitude distributionmeasured_amplitude
.- Returns
Average radius of the farfield spot.
- Return type
float