Skip to content

Commit d5a6653

Browse files
NickHallPhysicscarandraug
authored andcommitted
ximea: add DeepSIM changes.
1 parent 07c236f commit d5a6653

File tree

1 file changed

+125
-71
lines changed

1 file changed

+125
-71
lines changed

microscope/cameras/ximea.py

Lines changed: 125 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -27,43 +27,25 @@
2727
from microscope import devices
2828
from microscope.devices import keep_acquiring
2929

30-
#import ximea python module.
30+
# import ximea python module.
3131
from ximea import xiapi
3232

33-
34-
# Trigger mode to type.
35-
TRIGGER_MODES = {
36-
'internal': None,
37-
'external': devices.TRIGGER_BEFORE,
38-
'external start': None,
39-
'external exposure': devices.TRIGGER_DURATION,
40-
'software': devices.TRIGGER_SOFT,
33+
trigger_type_to_value = {
34+
0: 'XI_TRG_SOFTWARE',
35+
1: 'XI_TRG_EDGE_RISING',
4136
}
4237

43-
#trig types from define file....
44-
# #structure containing information about trigger source
45-
# XI_TRG_SOURCE = {
46-
# "XI_TRG_OFF": c_uint(0), #Camera works in free run mode.
47-
# "XI_TRG_EDGE_RISING": c_uint(1), #External trigger (rising edge).
48-
# "XI_TRG_EDGE_FALLING": c_uint(2), #External trigger (falling edge).
49-
# "XI_TRG_SOFTWARE": c_uint(3), #Software(manual) trigger.
50-
# "XI_TRG_LEVEL_HIGH": c_uint(4), #Specifies that the trigger is considered valid as long as the level of the source signal is high.
51-
# "XI_TRG_LEVEL_LOW": c_uint(5), #Specifies that the trigger is considered valid as long as the level of the source signal is low.
52-
# }
53-
54-
55-
5638

5739
@Pyro4.expose
5840
@Pyro4.behavior('single')
5941
class XimeaCamera(devices.CameraDevice):
6042
def __init__(self, *args, **kwargs):
6143
super(XimeaCamera, self).__init__(**kwargs)
62-
#example parameter to allow setting.
63-
# self.add_setting('_error_percent', 'int',
64-
# lambda: self._error_percent,
65-
# self._set_error_percent,
66-
# lambda: (0, 100))
44+
# example parameter to allow setting.
45+
# self.add_setting('_error_percent', 'int',
46+
# lambda: self._error_percent,
47+
# self._set_error_percent,
48+
# lambda: (0, 100))
6749
self._acquiring = False
6850
self._exposure_time = 0.1
6951
self._triggered = False
@@ -76,14 +58,35 @@ def _create_buffers(self):
7658
"""Create buffers and store values needed to remove padding later."""
7759
self._purge_buffers()
7860
self._logger.info("Creating buffers.")
79-
#time.sleep(0.5)
61+
# time.sleep(0.5)
8062

8163
def _fetch_data(self):
82-
if self._acquiring and self._triggered:
83-
self.handle.get_image(self.img)
84-
self._logger.info('Sending image')
85-
self._triggered = False
86-
return self.img.get_image_data_raw()
64+
trigger_type = self.handle.get_trigger_source()
65+
if trigger_type == 'XI_TRG_SOFTWARE':
66+
if self._acquiring and self._triggered:
67+
try:
68+
self.handle.get_image(self.img)
69+
data = self.img.get_image_data_numpy()
70+
self._logger.info("Fetched imaged with dims %s and size %s." % (data.shape, data.size))
71+
self._logger.info('Sending image')
72+
self._triggered = False
73+
return self.img.get_image_data_numpy()
74+
except Exception as err:
75+
self._logger.info('Get image error %s' % err)
76+
raise
77+
elif trigger_type == 'XI_TRG_EDGE_RISING':
78+
if self._acquiring:
79+
try:
80+
self.handle.get_image(self.img)
81+
data = self.img.get_image_data_numpy()
82+
self._logger.info("Fetched imaged with dims %s and size %s." % (data.shape, data.size))
83+
self._logger.info('Sending image')
84+
return self.img.get_image_data_numpy()
85+
except Exception as err:
86+
if err.args is xiapi.Xi_error(10).args:
87+
return None
88+
else:
89+
self._logger.info('Get image error %s' % err)
8790

8891
def abort(self):
8992
self._logger.info('Disabling acquisition.')
@@ -104,11 +107,32 @@ def initialize(self):
104107
raise Exception("Problem opening camera.")
105108
if self.handle == None:
106109
raise Exception("No camera opened.")
107-
108-
# for name, var in sorted(self.__dict__.items()):
110+
111+
# for name, var in sorted(self.__dict__.items()):
109112
self._logger.info('Initializing.')
110-
#create img buffer to hold images.
111-
self.img=xiapi.Image()
113+
# Try set camera into rising-edge hardware trigger mode. If that can't be done
114+
# set it to software trigger mode
115+
try:
116+
self.handle.set_trigger_source('XI_TRG_EDGE_RISING')
117+
except:
118+
self.handle.set_trigger_source('XI_TRG_SOFTWARE')
119+
# create img buffer to hold images.
120+
121+
self.img = xiapi.Image()
122+
123+
def get_current_image(self):
124+
self._logger.info('In get_current_image')
125+
try:
126+
if self._acquiring and self._triggered:
127+
self.handle.get_image(self.img)
128+
data = self.img.get_image_data_numpy()
129+
self._logger.info("Fetched imaged with dims %s and size %s." % (data.shape, data.size))
130+
self._logger.info('Sending image')
131+
self._triggered = False
132+
return data
133+
except Exception as e:
134+
self._logger.info("Error in ximeaCam: %s" % (e))
135+
raise Exception(str(xiapi.Xi_error(e.status)))
112136

113137
def make_safe(self):
114138
if self._acquiring:
@@ -123,71 +147,101 @@ def _on_enable(self):
123147
self.abort()
124148
self._create_buffers()
125149
self._acquiring = True
126-
#actually start camera
150+
# actually start camera
127151
self.handle.start_acquisition()
128152
self._logger.info("Acquisition enabled.")
129153
return True
130154

155+
# def enable(self):
156+
# self._on_enable()
157+
131158
def set_exposure_time(self, value):
132-
#exposure times are set in us.
133-
self.handle.set_exposure(value*1.0E6)
159+
# exposure times are set in us.
160+
try:
161+
self.handle.set_exposure(int(value * 1000000))
162+
except Exception as err:
163+
self._logger.debug("set_exposure_time exception: %s" % err)
134164

135165
def get_exposure_time(self):
136-
#exposure times are in us, so multiple by 1E-6 to get seconds.
137-
return (self.handle.get_exposure()*1.0E-6)
166+
# exposure times are in us, so multiple by 1E-6 to get seconds.
167+
return (self.handle.get_exposure() * 1.0E-6)
138168

139169
def get_cycle_time(self):
140-
return (self.handle.get_exposure()*1.0E-6)
170+
return (self.handle.get_exposure() * 1.0E-6)
141171

142172
def _get_sensor_shape(self):
143-
return (self.img.width,self.image.height)
144-
145-
#trig types from define file....
146-
# #structure containing information about trigger source
147-
# XI_TRG_SOURCE = {
148-
# "XI_TRG_OFF": c_uint(0), #Camera works in free run mode.
149-
# "XI_TRG_EDGE_RISING": c_uint(1), #External trigger (rising edge).
150-
# "XI_TRG_EDGE_FALLING": c_uint(2), #External trigger (falling edge).
151-
# "XI_TRG_SOFTWARE": c_uint(3), #Software(manual) trigger.
152-
# "XI_TRG_LEVEL_HIGH": c_uint(4), #Specifies that the trigger is considered valid as long as the level of the source signal is high.
153-
# "XI_TRG_LEVEL_LOW": c_uint(5), #Specifies that the trigger is considered valid as long as the level of the source signal is low.
154-
# }
173+
return (self.handle.get_width(), self.handle.get_height())
174+
175+
def get_trigger_source(self):
176+
return (self.handle.get_trigger_source())
155177

156178
def get_trigger_type(self):
157-
trig=self.handle.get_trigger_source()
158-
return devices.TRIGGER_SOFT
159-
160-
def set_trigger_type(self, trigger):
161-
if (trigger == devices.TRIGGER_SOFT):
162-
self.handle.set_triger_source(XI_TG_SOURCE['Xi_TRG_SOFTWARE'])
163-
elif (trigger == devices.TRIGGER_BEFORE):
164-
self.handle.set_triger_source(XI_TG_SOURCE['Xi_TRG_EDGE_RISING'])
165-
#define digial input mode of trigger
166-
self.handle.set_gpi_selector(1)
167-
self.handle.set_gpi_mode(XI_GPI_TRIGGER)
179+
trig = self.handle.get_trigger_source()
180+
self._logger.info("called get trigger type %s" % trig)
181+
if trig == 'XI_TRG_SOFTWARE':
182+
return devices.TRIGGER_SOFT
183+
elif trig == 'XI_TRG_EDGE_RISING':
184+
return devices.TRIGGER_BEFORE
185+
186+
def set_trigger_source(self, trig):
187+
self._logger.info("Set trigger source %s" % (trig))
188+
reenable = False
189+
if self._acquiring:
190+
self.abort()
191+
reenable = True
192+
result = self.handle.set_trigger_source(trig)
193+
self._logger.info("Set trigger source result %s" % (result))
194+
if reenable:
195+
self._on_enable()
196+
return
197+
198+
def set_trigger_type(self, trig):
199+
self._logger.info("Set trigger type %s" % (trig))
200+
self.abort()
201+
202+
if trig is 0:
203+
self.handle.set_trigger_source('XI_TRG_SOFTWARE')
204+
elif trig is 1:
205+
self.handle.set_trigger_source('XI_TRG_EDGE_RISING')
206+
# define digial input mode of trigger
207+
self.handle.set_gpi_selector('XI_GPI_PORT1')
208+
self.handle.set_gpi_mode('XI_GPI_TRIGGER')
209+
self.handle.set_gpo_selector('XI_GPO_PORT1')
210+
self.handle.set_gpo_mode('XI_GPO_EXPOSURE_ACTIVE')
211+
212+
self._on_enable()
213+
214+
result = self.handle.get_trigger_source()
215+
self._logger.info("Trigger type %s" % result)
216+
self._logger.info("GPI Selector %s" % self.handle.get_gpi_selector())
217+
self._logger.info("GPI Mode %s" % self.handle.get_gpi_mode())
218+
219+
return
220+
# return(self.handle.set_trigger_source(TRIGGER_MODES[trig]))
168221

169222
def soft_trigger(self):
170-
self._logger.info('Trigger received; self._acquiring is %s.'
223+
self._logger.info('Soft trigger received; self._acquiring is %s.'
171224
% self._acquiring)
172225
if self._acquiring:
226+
self.handle.set_trigger_software(True)
173227
self._triggered = True
174228

175229
def _get_binning(self):
176-
return (1,1)
230+
return (1, 1)
177231

178232
@keep_acquiring
179233
def _set_binning(self, h, v):
180234
return False
181235

182236
def _get_roi(self):
183-
return (0, 0, 512, 512)
237+
size = self._get_sensor_shape()
238+
return (0, 0, size[0], size[1])
184239

185240
@keep_acquiring
186241
def _set_roi(self, x, y, width, height):
187242
return False
188243

189244
def _on_shutdown(self):
190-
if self_.acquiring:
245+
if self._acquiring:
191246
self.handle.stop_acquisition()
192247
self.handle.close_device()
193-

0 commit comments

Comments
 (0)