2727from microscope import devices
2828from microscope .devices import keep_acquiring
2929
30- #import ximea python module.
30+ # import ximea python module.
3131from 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' )
5941class 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