Wavefront Sensor

In pyRTC, one of the core components is the wavefront sensor object. It typically starts the AO chain by running a continues capture sequence of images. This object is the producer of the wfs and wfsRaw shared memory objects which contain the dark subtracted and original image respectively. The images can then be processed by the slopesProcess class to compute the intermediate data product used for wavefront reconstruction.

Soft-RTC Example

The following is an example of how to initialize a WavefrontSensor component in pyRTC. Here we are in the soft-RTC mode of pyRTC, which holds all components in the same python process. See below for how to launch a hard-RTC equivalent.

"""
First we import the relevant wavefront sensor class. Typically, this will be a
specific hardware class which has been defined to work with the SDK of your camera.

As an example (see hardware/ximeaWFS.py):

from pyRTC.hardware import XIMEA_WFS

Here, I will just initialize the Wavefront Sensor Superclass as an example
"""

#%% Run in interactive python or jupyter notebook to keep process alive
from pyRTC.WavefrontSensor import WavefrontSensor
import matplotlib.pyplot as plt
from pyRTC.utils import read_yaml_file

confWFS = {
"name": "example",
"width": 256,
"height": 256,
"darkCount": 1000,
"darkFile": "", #Here you can add a dark file, if existing "./EXAMPLE/calib/wfsDark.npy",
"affinity": 2,
"functions": ["expose"]
}

"""
Alternatively, read the config from a file

conf = read_yaml_file("./EXAMPLE/config.yaml")["wfs"]
"""

#Initialize the WFS object
wfs = WavefrontSensor(confWFS)
#Start the functions regiserted to the loop (i.e, expose)
wfs.start()

img = wfs.read()


plt.imshow(img)
plt.show()


"""
Monitor the SHM in realtime by running the viewer command in a terminal
pyrtc-view wfs &
"""

Hard-RTC Example

The following is an example of how to initialize a WavefrontSensor component in pyRTC. Here we are in the hard-RTC mode of pyRTC, which holds all components in the separate python processes. This circumvents the python Global Interpreter Lock See above for how to launch a soft-RTC equivalent.

from pyRTC.Pipeline import hardwareLauncher

"""
For the Hard-RTC, you will need to set-up a config before hand and store it in a yaml file.

It should look something like:

wfs:
  name: XIMEA
  serial: "46052550"
  binning: 1
  exposure: 2000
  gain: 0
  bitDepth: 10
  left: 448
  top: 280
  width: 400
  height: 400
  darkCount: 2000
  darkFile: "/home/whetstone/pyRTC/examples/sharp_lab/calib/dark.npy"
  affinity: 3
  functions:
  - expose
"""
config = 'path/to/config.yaml'
port = 3000

#Initialize the hardware launcher for your WFS child hardware class
wfs = hardwareLauncher('path/to/pyRTC/hardware/myHardwareWfs.py',config,port)
"""
Launch the process.

This will run the hardware file, which should establish a connection with the current process.
This is accomplished with the Listener class (see hardware folder for examples).

The functions registered in the config to the real-time loop will automatically be started.
"""
wfs.launch()

"""
Once the connection has been made successfully, you can run any function in the hardware class
using the run function. You can also get and set properties of the hardware using getProperty()
and setProperty() respectively.
"""
wfs.run("expose")

wfs.setProperty("exposure", 100)

print(wfs.getProperty("exposure"))

Parameters

class pyRTC.WavefrontSensor.WavefrontSensor(conf)[source]

Bases: pyRTCComponent

Base class for cameras that feed the wavefront-sensing pipeline.

The class owns the common control-plane behavior for wavefront-sensor image sources: configuration, dark subtraction, optional downsampling and rotation, and publication of both raw and processed frames. Concrete sensor adapters in pyRTC.hardware are responsible for talking to vendor SDKs and filling self.data before delegating back to the base implementation.

Config

namestr

The name of the wavefront sensor. Default “wavefrontSensor”

widthint

The width of the wavefront sensor image. Required.

heightint

The width of the wavefront sensor image. Required.

darkCountint

Number of dark frames to average. Default 1000.

darkFilestr

Path to the dark frame file. Default, empty string.

Attributes

imageShapetuple

The shape of the image (width, height).

imageRawDTypedata-type

The data type for raw image.

imageDTypedata-type

The data type for processed image.

imageRawImageSHM

Shared memory object for raw image.

imageImageSHM

Shared memory object for processed image.

datandarray

Array to store raw image data.

darkndarray

Array to store dark frame data.

affinityint

The affinity configuration.

roiWidthint

Width of the region of interest.

roiHeightint

Height of the region of interest.

roiLeftint

Left coordinate of the region of interest.

roiTopint

Top coordinate of the region of interest.

exposurefloat

Exposure time.

binningint

Binning factor.

gainfloat

Gain setting.

bitDepthint

Bit depth of the image.

Methods

setRoi(roi)

Sets the region of interest.

setExposure(exposure)

Sets the exposure time.

setBinning(binning)

Sets the binning factor.

setGain(gain)

Sets the gain.

setBitDepth(bitDepth)

Sets the bit depth.

expose()

Writes the current image data to shared memory.

read()

Reads the processed image data from shared memory.

takeDark()

Captures and sets the dark frame.

setDark(dark)

Sets the dark frame.

saveDark(filename=’’)

Saves the dark frame to a file.

loadDark(filename=’’)

Loads the dark frame from a file.

plot()

Plots the current image data.

rotateImage(angle_deg)

Rotates the current image data by the specified angle in degrees.

expose()[source]

Writes the current image data to shared memory. Both raw, and dark subtracted.

Parameters

Return type:

None

loadDark(filename='')[source]

Loads the dark frame from a file.

Parameters

filenamestr, optional

Filename to load the dark frame from. If not specified, uses the dark file path from the configuration.

plot()[source]

Plots the current image data.

Return type:

None

read(block=True)[source]

Reads the dark subtracted image data from shared memory.

Returns

ndarray

Processed image data.

Return type:

None

rotateImage(angle_deg)[source]

Rotates the current image data by the specified angle.

This method uses a high-performance numba JIT-compiled bilinear interpolation rotation algorithm that is significantly faster than scipy or opencv implementations while maintaining good image quality.

Parameters

angle_degfloat

Rotation angle in degrees. Positive values rotate counter-clockwise.

Returns

ndarray

Rotated image data with the same shape and dtype as the original.

Examples

>>> wfs = WavefrontSensor(config)
>>> rotated_img = wfs.rotateImage(45.0)  # Rotate 45 degrees counter-clockwise
>>> rotated_img = wfs.rotateImage(-90.0) # Rotate 90 degrees clockwise
Parameters:

angle_deg (float)

Return type:

ndarray

saveDark(filename='')[source]

Saves the dark frame to a file.

Parameters

filenamestr, optional

Filename to save the dark frame to. If not specified, uses the dark file path from the configuration.

setBinning(binning)[source]

Sets the binning factor for the sensor.

Parameters

binningint

Binning factor.

Parameters:

binning (int)

Return type:

None

setBitDepth(bitDepth)[source]

Sets the bit depth for the sensor.

Parameters

bitDepthint

Bit depth. pyRTC convention is this is the number of bits in the ADC, e.g., 8, 16, 12, 10.

Parameters:

bitDepth (int)

Return type:

None

setDark(dark)[source]

Sets the dark frame.

Parameters

darkndarray

Dark frame data.

Return type:

None

setExposure(exposure)[source]

Sets the exposure time for the sensor.

Parameters

exposurefloat

Exposure time in whatever unit your camera uses.

Parameters:

exposure (float)

Return type:

None

setGain(gain)[source]

Sets the gain for the sensor.

Parameters

gainfloat

Gain value.

Parameters:

gain (float)

Return type:

None

setRoi(roi)[source]

Sets the region of interest (ROI) for the sensor.

Parameters

roituple

A tuple containing (width, height, left, top) of the ROI.

start()

Start the registered real-time functions.

stop()

Stops the registered real-time functions.

takeDark()[source]

Captures and sets the dark frame.

Return type:

None

Parameters:

conf (dict)