Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reset properties while acquisition in Hamamatsu camera service #211

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions catkit2/services/allied_vision_camera/allied_vision_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
from catkit2.testbed.service import Service


def _create_property(property_name, read_only=False, stopped_acquisition=True):
def _create_property(av_property_name, read_only=False, stopped_acquisition=True):
def getter(self):
with self.mutex:
return getattr(self.cam, property_name).get()
return getattr(self.cam, av_property_name).get()

if read_only:
setter = None
Expand All @@ -41,7 +41,7 @@ def setter(self, value):
time.sleep(0.001)

with self.mutex:
getattr(self.cam, property_name).set(value)
getattr(self.cam, av_property_name).set(value)

if was_running and stopped_acquisition:
self.start_acquisition()
Expand Down
298 changes: 61 additions & 237 deletions catkit2/services/hamamatsu_camera/hamamatsu_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import os
import sys
import threading
import time
import numpy as np
from catkit2.testbed.service import Service

Expand All @@ -21,6 +22,38 @@
raise


def _create_property(hamamatsu_property_name, read_only=False, stopped_acquisition=True):
def getter(self):
with self.mutex:
if hamamatsu_property_name != 'EXPOSURETIME':
return self.cam.prop_getvalue(getattr(dcam.DCAM_IDPROP, hamamatsu_property_name))
else:
return self.cam.prop_getvalue(getattr(dcam.DCAM_IDPROP, hamamatsu_property_name)) * 1e6

if read_only:
setter = None
else:
def setter(self, value):
was_running = self.is_acquiring.get()[0] > 0

if was_running and stopped_acquisition:
self.end_acquisition()

while self.is_acquiring.get()[0]:
time.sleep(0.001)

with self.mutex:
if hamamatsu_property_name != 'EXPOSURETIME':
self.cam.prop_setvalue(getattr(dcam.DCAM_IDPROP, hamamatsu_property_name), value)
else:
self.cam.prop_setvalue(getattr(dcam.DCAM_IDPROP, hamamatsu_property_name), value / 1e6)

if was_running and stopped_acquisition:
self.start_acquisition()

return property(getter, setter)


class HamamatsuCamera(Service):
"""
Service for Hamamatsu cameras.
Expand Down Expand Up @@ -73,6 +106,9 @@ def __init__(self):
self.should_be_acquiring = threading.Event()
self.should_be_acquiring.set()

# Create lock for camera access
self.mutex = threading.Lock()

def open(self):
"""
Open the service.
Expand Down Expand Up @@ -131,19 +167,6 @@ def open(self):
self.log.info('Using pixel format: %s', self.current_pixel_format)
self.cam.prop_setvalue(dcam.DCAM_IDPROP.IMAGE_PIXELTYPE, self.pixel_formats[self.current_pixel_format])

# Set device values from config file (set width and height before offsets)
offset_x = self.config.get('offset_x', 0)
offset_y = self.config.get('offset_y', 0)

self.width = self.config.get('width', self.sensor_width - offset_x)
self.height = self.config.get('height', self.sensor_height - offset_y)
self.offset_x = offset_x
self.offset_y = offset_y

self.gain = self.config.get('gain', 0)
self.exposure_time = self.config.get('exposure_time', 1000)
self.temperature = self.make_data_stream('temperature', 'float64', [1], 20)

# Create datastreams
# Use the full sensor size here to always allocate enough shared memory.
self.images = self.make_data_stream('images', 'float32', [self.sensor_height, self.sensor_width], self.NUM_FRAMES)
Expand All @@ -158,6 +181,19 @@ def make_property_helper(name, read_only=False):
else:
self.make_property(name, lambda: getattr(self, name), lambda val: setattr(self, name, val))

# Set device values from config file (set width and height before offsets)
offset_x = self.config.get('offset_x', 0)
offset_y = self.config.get('offset_y', 0)

self.width = self.config.get('width', self.sensor_width - offset_x)
self.height = self.config.get('height', self.sensor_height - offset_y)
self.offset_x = offset_x
self.offset_y = offset_y

self.gain = self.config.get('gain', 0)
self.exposure_time = self.config.get('exposure_time', 1000)
self.temperature = self.make_data_stream('temperature', 'float64', [1], 20)

make_property_helper('exposure_time')
make_property_helper('gain')
make_property_helper('brightness')
Expand Down Expand Up @@ -268,6 +304,18 @@ def end_acquisition(self):
"""
self.should_be_acquiring.clear()

exposure_time = _create_property('EXPOSURETIME', stopped_acquisition=False)
gain = _create_property('CONTRASTGAIN', stopped_acquisition=False)
brightness = _create_property('SENSITIVITY', stopped_acquisition=False)

width = _create_property('SUBARRAYHSIZE')
height = _create_property('SUBARRAYVSIZE')
offset_x = _create_property('SUBARRAYVPOS')
offset_y = _create_property('SUBARRAYHPOS')

sensor_width = _create_property('IMAGE_WIDTH', read_only=True)
sensor_height = _create_property('IMAGE_HEIGHT', read_only=True)

def get_temperature(self):
"""
Get the temperature of the camera.
Expand All @@ -281,230 +329,6 @@ def get_temperature(self):
"""
return self.cam.prop_getvalue(dcam.DCAM_IDPROP.SENSORTEMPERATURE)

@property
def exposure_time(self):
"""
The exposure time in microseconds.

This property can be used to get the exposure time of the camera.

Returns:
--------
float:
The exposure time in microseconds.
"""
return self.cam.prop_getvalue(dcam.DCAM_IDPROP.EXPOSURETIME) * 1e6

@exposure_time.setter
def exposure_time(self, exposure_time: float):
"""
Set the exposure time in microseconds.

This property can be used to set the exposure time of the camera.

Parameters
----------
exposure_time : float
The exposure time in microseconds.
"""
self.cam.prop_setvalue(dcam.DCAM_IDPROP.EXPOSURETIME, exposure_time / 1e6)

@property
def gain(self):
"""
The gain of the camera.

This property can be used to get the gain of the camera.

Returns:
--------
int:
The gain of the camera.
"""
return self.cam.prop_getvalue(dcam.DCAM_IDPROP.CONTRASTGAIN)

@gain.setter
def gain(self, gain: int):
"""
Set the gain of the camera.

This property can be used to set the gain of the camera.

Parameters
----------
gain : int
The gain of the camera.
"""
self.cam.prop_setvalue(dcam.DCAM_IDPROP.CONTRASTGAIN, gain)

@property
def brightness(self):
"""
The brightness of the camera.

This property can be used to get the brightness of the camera.

Returns:
--------
int:
The brightness of the camera.
"""
return self.cam.prop_getvalue(dcam.DCAM_IDPROP.SENSITIVITY)

@brightness.setter
def brightness(self, brightness: int):
"""
Set the brightness of the camera.

This property can be used to set the brightness of the camera.

Parameters
----------
brightness : int
The brightness of the camera.
"""
self.cam.prop_setvalue(dcam.DCAM_IDPROP.SENSITIVITY, brightness)

@property
def sensor_width(self):
"""
The width of the sensor in pixels.

This property can be used to get the width of the sensor in pixels.

Returns:
--------
int:
The width of the sensor in pixels.
"""
return int(self.cam.prop_getvalue(dcam.DCAM_IDPROP.IMAGE_WIDTH))

@property
def sensor_height(self):
"""
The height of the sensor in pixels.

This property can be used to get the height of the sensor in pixels.

Returns:
--------
int:
The height of the sensor in pixels.
"""
return int(self.cam.prop_getvalue(dcam.DCAM_IDPROP.IMAGE_HEIGHT))

@property
def width(self):
"""
The width of the image in pixels.

This property can be used to get the width of the image in pixels.

Returns:
--------
int:
The width of the image in pixels.
"""
return int(self.cam.prop_getvalue(dcam.DCAM_IDPROP.SUBARRAYHSIZE))

@width.setter
def width(self, width: int):
"""
Set the width of the image in pixels.

This property can be used to set the width of the image in pixels.

Parameters
----------
width : int
The width of the image in pixels.
"""
self.cam.prop_setvalue(dcam.DCAM_IDPROP.SUBARRAYHSIZE, width)

@property
def height(self):
"""
The height of the image in pixels.

This property can be used to get the height of the image in pixels.

Returns:
--------
int:
The height of the image in pixels.
"""
return int(self.cam.prop_getvalue(dcam.DCAM_IDPROP.SUBARRAYVSIZE))

@height.setter
def height(self, height: int):
"""
Set the height of the image in pixels.

This property can be used to set the height of the image in pixels.

Parameters
----------
height : int
The height of the image in pixels.
"""
self.cam.prop_setvalue(dcam.DCAM_IDPROP.SUBARRAYVSIZE, height)

@property
def offset_x(self):
"""
The x offset of the image in pixels.

This property can be used to get the x offset of the image in pixels.

Returns:
--------
int:
The x offset of the image in pixels.
"""
return self.cam.prop_getvalue(dcam.DCAM_IDPROP.SUBARRAYVPOS)

@offset_x.setter
def offset_x(self, offset_x: int):
"""
Set the x offset of the image in pixels.

This property can be used to set the x offset of the image in pixels.

Parameters
----------
offset_x : int
The x offset of the image in pixels.
"""
self.cam.prop_setvalue(dcam.DCAM_IDPROP.SUBARRAYVPOS, offset_x)

@property
def offset_y(self):
"""
The y offset of the image in pixels.

This property can be used to get the y offset of the image in pixels.

Returns:
--------
int:
The y offset of the image in pixels.
"""
return self.cam.prop_getvalue(dcam.DCAM_IDPROP.SUBARRAYHPOS)

@offset_y.setter
def offset_y(self, offset_y: int):
"""
Set the y offset of the image in pixels.

This property can be used to set the y offset of the image in pixels.

Parameters
----------
offset_y : int
The y offset of the image in pixels.
"""
self.cam.prop_setvalue(dcam.DCAM_IDPROP.SUBARRAYHPOS, offset_y)


if __name__ == '__main__':
service = HamamatsuCamera()
Expand Down
Loading