2121
2222import logging
2323
24- import numpy as np
24+ from ximea import xiapi
2525
2626from microscope import devices
27- from microscope .devices import keep_acquiring , ROI
28-
29- #import ximea python module.
30- from ximea import xiapi
3127
3228
3329_logger = logging .getLogger (__name__ )
3430
3531
36- # Trigger mode to type.
37- TRIGGER_MODES = {
38- 'internal' : None ,
39- 'external' : devices .TRIGGER_BEFORE ,
40- 'external start' : None ,
41- 'external exposure' : devices .TRIGGER_DURATION ,
42- 'software' : devices .TRIGGER_SOFT ,
43- }
44-
45- #trig types from define file....
46- # XI_TRG_SOURCE = {
47- # "XI_TRG_OFF": c_uint(0), #Camera works in free run mode.
48- # "XI_TRG_EDGE_RISING": c_uint(1), #External trigger (rising edge).
49- # "XI_TRG_EDGE_FALLING": c_uint(2), #External trigger (falling edge).
50- # "XI_TRG_SOFTWARE": c_uint(3), #Software(manual) trigger.
51- # "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.
52- # "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.
53- # }
54-
55-
5632class XimeaCamera (devices .CameraDevice ):
57- def __init__ (self , ** kwargs ):
33+ def __init__ (self , dev_id = 0 , ** kwargs ):
5834 super ().__init__ (** kwargs )
5935 self ._acquiring = False
6036 self ._exposure_time = 0.1
6137 self ._triggered = False
62- self .Roi = ROI (None ,None ,None ,None )
38+ self ._handle = None
39+ self ._dev_id = dev_id
40+ self ._roi = devices .ROI (None ,None ,None ,None )
6341
6442 def _fetch_data (self ):
65- if self ._acquiring and self ._triggered :
66- self .handle .get_image (self .img )
43+ if not self ._acquiring :
44+ return
45+
46+ trigger_type = self ._handle .get_trigger_source ()
47+ if trigger_type == 'XI_TRG_SOFTWARE' and not self ._triggered :
48+ return
49+ elif trigger_type != 'XI_TRG_EDGE_RISING' :
50+ raise Exception ('unhandled trigger type %s' % trigger_type )
51+
52+ try :
53+ self ._handle .get_image (self .img )
54+ data = self .img .get_image_data_numpy ()
55+ _logger .info ("Fetched imaged with dims %s and size %s." ,
56+ data .shape , data .size )
6757 _logger .info ('Sending image' )
68- self ._triggered = False
69- data = np .array (list (self .img .get_image_data_raw ()),dtype = np .uint16 ).reshape (self .img .width ,self .img .height )
70- return data
58+ if trigger_type == 'XI_TRG_SOFTWARE' :
59+ self ._triggered = False
60+ return self .img .get_image_data_numpy ()
61+ except Exception as err :
62+ if getattr (err , 'status' , None ) == 10 :
63+ # This is a Timeout error
64+ return
65+ else :
66+ raise err
7167
7268 def abort (self ):
7369 _logger .info ('Disabling acquisition.' )
7470 if self ._acquiring :
7571 self ._acquiring = False
76- self .handle .stop_acquisition ()
72+ self ._handle .stop_acquisition ()
7773
7874 def initialize (self ):
7975 """Initialise the camera.
8076
8177 Open the connection, connect properties and populate settings dict.
8278 """
8379 try :
84- self .handle = xiapi .Camera ()
85- self .handle .open_device ()
80+ self ._handle = xiapi .Camera (self . _dev_id )
81+ self ._handle .open_device ()
8682 except :
8783 raise Exception ("Problem opening camera." )
88- if self .handle == None :
84+ if self ._handle == None :
8985 raise Exception ("No camera opened." )
86+
9087 _logger .info ('Initializing.' )
91- self .img = xiapi .Image ()
88+ # Try set camera into rising-edge hardware trigger mode. If
89+ # that can't be done set it to software trigger mode.
90+ try :
91+ self ._handle .set_trigger_source ('XI_TRG_EDGE_RISING' )
92+ except :
93+ self ._handle .set_trigger_source ('XI_TRG_SOFTWARE' )
94+ # create img buffer to hold images.
95+ self .img = xiapi .Image ()
9296
9397 def make_safe (self ):
9498 if self ._acquiring :
@@ -102,63 +106,96 @@ def _on_enable(self):
102106 if self ._acquiring :
103107 self .abort ()
104108 self ._acquiring = True
105- #actually start camera
106- self .handle .start_acquisition ()
109+ # actually start camera
110+ self ._handle .start_acquisition ()
107111 _logger .info ("Acquisition enabled." )
108112 return True
109113
110114 def set_exposure_time (self , value ):
111- #exposure times are set in us.
112- self .handle .set_exposure (int (value * 1.0E6 ))
115+ # exposure times are set in us.
116+ try :
117+ self ._handle .set_exposure (int (value * 1000000 ))
118+ except Exception as err :
119+ _logger .debug ("set_exposure_time exception: %s" , err )
113120
114121 def get_exposure_time (self ):
115- #exposure times are in us, so multiple by 1E-6 to get seconds.
116- return (self .handle .get_exposure ()* 1.0E-6 )
122+ # exposure times are in us, so multiple by 1E-6 to get seconds.
123+ return (self ._handle .get_exposure () * 1.0E-6 )
117124
118125 def get_cycle_time (self ):
119- return (1.0 / self .handle .get_framerate ())
126+ return (1.0 / self ._handle .get_framerate ())
120127
121128 def _get_sensor_shape (self ):
122- return (self .img . width , self .img . height )
129+ return (self ._handle . get_width (), self ._handle . get_height () )
123130
131+ def get_trigger_source (self ):
132+ return (self ._handle .get_trigger_source ())
124133
125134 def get_trigger_type (self ):
126- trig = self .handle .get_trigger_source ()
127- if trig == XI_TRG_SOFTWARE :
135+ trig = self ._handle .get_trigger_source ()
136+ _logger .info ("called get trigger type %s" , trig )
137+ if trig == 'XI_TRG_SOFTWARE' :
128138 return devices .TRIGGER_SOFT
129- elif trig == XI_TRG_EDGE_RISING :
139+ elif trig == ' XI_TRG_EDGE_RISING' :
130140 return devices .TRIGGER_BEFORE
131141
132- def set_trigger_type (self , trigger ):
133- if (trigger == devices .TRIGGER_SOFT ):
134- self .handle .set_triger_source (XI_TG_SOURCE ['Xi_TRG_SOFTWARE' ])
135- elif (trigger == devices .TRIGGER_BEFORE ):
136- self .handle .set_triger_source (XI_TG_SOURCE ['Xi_TRG_EDGE_RISING' ])
137- #define digial input mode of trigger
138- self .handle .set_gpi_selector (1 )
139- self .handle .set_gpi_mode (XI_GPI_TRIGGER )
142+ def set_trigger_source (self , trig ):
143+ _logger .info ("Set trigger source %s" , trig )
144+ reenable = False
145+ if self ._acquiring :
146+ self .abort ()
147+ reenable = True
148+ result = self ._handle .set_trigger_source (trig )
149+ _logger .info ("Set trigger source result %s" , result )
150+ if reenable :
151+ self ._on_enable ()
152+ return
153+
154+ def set_trigger_type (self , trig ):
155+ _logger .info ("Set trigger type %s" , trig )
156+ self .abort ()
157+
158+ if trig is 0 :
159+ self ._handle .set_trigger_source ('XI_TRG_SOFTWARE' )
160+ elif trig is 1 :
161+ self ._handle .set_trigger_source ('XI_TRG_EDGE_RISING' )
162+ # define digial input mode of trigger
163+ self ._handle .set_gpi_selector ('XI_GPI_PORT1' )
164+ self ._handle .set_gpi_mode ('XI_GPI_TRIGGER' )
165+ self ._handle .set_gpo_selector ('XI_GPO_PORT1' )
166+ self ._handle .set_gpo_mode ('XI_GPO_EXPOSURE_ACTIVE' )
167+
168+ self ._on_enable ()
169+
170+ result = self ._handle .get_trigger_source ()
171+ _logger .info ("Trigger type %s" , result )
172+ _logger .info ("GPI Selector %s" , self ._handle .get_gpi_selector ())
173+ _logger .info ("GPI Mode %s" , self ._handle .get_gpi_mode ())
174+
175+ return
140176
141177 def soft_trigger (self ):
142- _logger .info ('Trigger received; self._acquiring is %s.'
143- % self ._acquiring )
178+ _logger .info ('Soft trigger received; self._acquiring is %s.' ,
179+ self ._acquiring )
144180 if self ._acquiring :
181+ self ._handle .set_trigger_software (True )
145182 self ._triggered = True
146183
147184 def _get_binning (self ):
148- return (1 ,1 )
185+ return (1 , 1 )
149186
150- @keep_acquiring
187+ @devices . keep_acquiring
151188 def _set_binning (self , h , v ):
152189 return False
153190
154191 def _get_roi (self ):
155- return self .Roi
192+ return self ._roi
156193
157- @keep_acquiring
194+ @devices . keep_acquiring
158195 def _set_roi (self , x , y , width , height ):
159- self .Roi = ROI (x , y , width , height )
196+ self ._roi = devices . ROI (x , y , width , height )
160197
161198 def _on_shutdown (self ):
162199 if self ._acquiring :
163- self .handle .stop_acquisition ()
164- self .handle .close_device ()
200+ self ._handle .stop_acquisition ()
201+ self ._handle .close_device ()
0 commit comments