@@ -155,115 +155,126 @@ async def setup(self, use_cam: bool = False) -> None:
155155 self ._shaking_task : Optional [asyncio .Task ] = None
156156
157157 if use_cam :
158- if not USE_PYSPIN :
159- raise RuntimeError (
160- "PySpin is not installed. Please follow the imaging setup instructions. "
161- f"Import error: { _PYSPIN_IMPORT_ERROR } "
162- )
163- if self .imaging_config is None :
164- raise RuntimeError ("Imaging configuration is not set." )
165-
166- logger .debug ("[cytation5] setting up camera" )
167-
168- # -- Retrieve singleton reference to system object (Spinnaker) --
169- self .spinnaker_system = PySpin .System .GetInstance ()
170- version = self .spinnaker_system .GetLibraryVersion ()
171- logger .debug (
172- "[cytation5] Library version: %d.%d.%d.%d" ,
173- version .major ,
174- version .minor ,
175- version .type ,
176- version .build ,
158+ try :
159+ await self ._set_up_camera ()
160+ except :
161+ # if setting up the camera fails, we have to close the ftdi connection
162+ # so that the user can try calling setup() again.
163+ # if we don't close the ftdi connection here, it will be open until the
164+ # python kernel is restarted.
165+ await self .stop ()
166+ raise
167+
168+ async def _set_up_camera (self ) -> None :
169+ if not USE_PYSPIN :
170+ raise RuntimeError (
171+ "PySpin is not installed. Please follow the imaging setup instructions. "
172+ f"Import error: { _PYSPIN_IMPORT_ERROR } "
177173 )
174+ if self .imaging_config is None :
175+ raise RuntimeError ("Imaging configuration is not set." )
176+
177+ logger .debug ("[cytation5] setting up camera" )
178+
179+ # -- Retrieve singleton reference to system object (Spinnaker) --
180+ self .spinnaker_system = PySpin .System .GetInstance ()
181+ version = self .spinnaker_system .GetLibraryVersion ()
182+ logger .debug (
183+ "[cytation5] Library version: %d.%d.%d.%d" ,
184+ version .major ,
185+ version .minor ,
186+ version .type ,
187+ version .build ,
188+ )
178189
179- # -- Get the camera by serial number, or the first. --
180- cam_list = self .spinnaker_system .GetCameras ()
181- num_cameras = cam_list .GetSize ()
182- logger .debug ("[cytation5] number of cameras detected: %d" , num_cameras )
183-
184- for cam in cam_list :
185- info = self ._get_device_info (cam )
186- serial_number = info ["DeviceSerialNumber" ]
187- logger .debug ("[cytation5] camera detected: %s" , serial_number )
188-
189- if (
190- self .imaging_config .camera_serial_number is not None
191- and serial_number == self .imaging_config .camera_serial_number
192- ):
193- self .cam = cam
194- logger .info ("[cytation5] using camera with serial number %s" , serial_number )
195- break
196- else : # if no specific camera was found by serial number so use the first one
197- if num_cameras > 0 :
198- self .cam = cam_list .GetByIndex (0 )
199- logger .info (
200- "[cytation5] using first camera with serial number %s" , info ["DeviceSerialNumber" ]
201- )
202- else :
203- logger .error ("[cytation5] no cameras found" )
204- self .cam = None
205- cam_list .Clear ()
190+ # -- Get the camera by serial number, or the first. --
191+ cam_list = self .spinnaker_system .GetCameras ()
192+ num_cameras = cam_list .GetSize ()
193+ logger .debug ("[cytation5] number of cameras detected: %d" , num_cameras )
206194
207- if self . cam is None :
208- raise RuntimeError (
209- "No camera found. Make sure the camera is connected and the serial " "number is correct."
210- )
195+ for cam in cam_list :
196+ info = self . _get_device_info ( cam )
197+ serial_number = info [ "DeviceSerialNumber" ]
198+ logger . debug ( "[cytation5] camera detected: %s" , serial_number )
211199
212- # -- Initialize camera --
213- for _ in range (10 ):
214- try :
215- self .cam .Init () # SpinnakerException: Spinnaker: Could not read the XML URL [-1010]
216- break
217- except : # noqa
218- pass
219- else :
220- raise RuntimeError (
221- "Failed to initialize camera. Make sure the camera is connected and the "
222- "Spinnaker SDK is installed correctly."
200+ if (
201+ self .imaging_config .camera_serial_number is not None
202+ and serial_number == self .imaging_config .camera_serial_number
203+ ):
204+ self .cam = cam
205+ logger .info ("[cytation5] using camera with serial number %s" , serial_number )
206+ break
207+ else : # if no specific camera was found by serial number so use the first one
208+ if num_cameras > 0 :
209+ self .cam = cam_list .GetByIndex (0 )
210+ logger .info (
211+ "[cytation5] using first camera with serial number %s" , info ["DeviceSerialNumber" ]
223212 )
224- nodemap = self .cam .GetNodeMap ()
213+ else :
214+ logger .error ("[cytation5] no cameras found" )
215+ self .cam = None
216+ cam_list .Clear ()
225217
226- # -- Configure trigger to be software --
227- # This is needed for longer exposure times (otherwise 23ms is the maximum)
228- # 1. Set trigger selector to frame start
229- ptr_trigger_selector = PySpin .CEnumerationPtr (nodemap .GetNode ("TriggerSelector" ))
230- if not PySpin .IsReadable (ptr_trigger_selector ) or not PySpin .IsWritable (ptr_trigger_selector ):
231- raise RuntimeError (
232- "unable to configure TriggerSelector " "(can't read or write TriggerSelector)"
233- )
234- ptr_frame_start = PySpin .CEnumEntryPtr (ptr_trigger_selector .GetEntryByName ("FrameStart" ))
235- if not PySpin .IsReadable (ptr_frame_start ):
236- raise RuntimeError ("unable to configure TriggerSelector (can't read FrameStart)" )
237- ptr_trigger_selector .SetIntValue (int (ptr_frame_start .GetNumericValue ()))
238-
239- # 2. Set trigger source to software
240- ptr_trigger_source = PySpin .CEnumerationPtr (nodemap .GetNode ("TriggerSource" ))
241- if not PySpin .IsReadable (ptr_trigger_source ) or not PySpin .IsWritable (ptr_trigger_source ):
242- raise RuntimeError ("unable to configure TriggerSource (can't read or write TriggerSource)" )
243- ptr_inference_ready = PySpin .CEnumEntryPtr (ptr_trigger_source .GetEntryByName ("Software" ))
244- if not PySpin .IsReadable (ptr_inference_ready ):
245- raise RuntimeError ("unable to configure TriggerSource (can't read Software)" )
246- ptr_trigger_source .SetIntValue (int (ptr_inference_ready .GetNumericValue ()))
247-
248- # 3. Set trigger mode to on
249- ptr_trigger_mode = PySpin .CEnumerationPtr (nodemap .GetNode ("TriggerMode" ))
250- if not PySpin .IsReadable (ptr_trigger_mode ) or not PySpin .IsWritable (ptr_trigger_mode ):
251- raise RuntimeError ("unable to configure TriggerMode (can't read or write TriggerMode)" )
252- ptr_trigger_on = PySpin .CEnumEntryPtr (ptr_trigger_mode .GetEntryByName ("On" ))
253- if not PySpin .IsReadable (ptr_trigger_on ):
254- raise RuntimeError ("unable to query TriggerMode On" )
255- ptr_trigger_mode .SetIntValue (int (ptr_trigger_on .GetNumericValue ()))
256-
257- # "NOTE: Blackfly and Flea3 GEV cameras need 1 second delay after trigger mode is turned on"
258- await asyncio .sleep (1 )
259-
260- # -- Load filter information --
261- if self ._filters is None :
262- await self ._load_filters ()
263-
264- # -- Load objective information --
265- if self ._objectives is None :
266- await self ._load_objectives ()
218+ if self .cam is None :
219+ raise RuntimeError (
220+ "No camera found. Make sure the camera is connected and the serial " "number is correct."
221+ )
222+
223+ # -- Initialize camera --
224+ for _ in range (10 ):
225+ try :
226+ self .cam .Init () # SpinnakerException: Spinnaker: Could not read the XML URL [-1010]
227+ break
228+ except : # noqa
229+ pass
230+ else :
231+ raise RuntimeError (
232+ "Failed to initialize camera. Make sure the camera is connected and the "
233+ "Spinnaker SDK is installed correctly."
234+ )
235+ nodemap = self .cam .GetNodeMap ()
236+
237+ # -- Configure trigger to be software --
238+ # This is needed for longer exposure times (otherwise 23ms is the maximum)
239+ # 1. Set trigger selector to frame start
240+ ptr_trigger_selector = PySpin .CEnumerationPtr (nodemap .GetNode ("TriggerSelector" ))
241+ if not PySpin .IsReadable (ptr_trigger_selector ) or not PySpin .IsWritable (ptr_trigger_selector ):
242+ raise RuntimeError (
243+ "unable to configure TriggerSelector " "(can't read or write TriggerSelector)"
244+ )
245+ ptr_frame_start = PySpin .CEnumEntryPtr (ptr_trigger_selector .GetEntryByName ("FrameStart" ))
246+ if not PySpin .IsReadable (ptr_frame_start ):
247+ raise RuntimeError ("unable to configure TriggerSelector (can't read FrameStart)" )
248+ ptr_trigger_selector .SetIntValue (int (ptr_frame_start .GetNumericValue ()))
249+
250+ # 2. Set trigger source to software
251+ ptr_trigger_source = PySpin .CEnumerationPtr (nodemap .GetNode ("TriggerSource" ))
252+ if not PySpin .IsReadable (ptr_trigger_source ) or not PySpin .IsWritable (ptr_trigger_source ):
253+ raise RuntimeError ("unable to configure TriggerSource (can't read or write TriggerSource)" )
254+ ptr_inference_ready = PySpin .CEnumEntryPtr (ptr_trigger_source .GetEntryByName ("Software" ))
255+ if not PySpin .IsReadable (ptr_inference_ready ):
256+ raise RuntimeError ("unable to configure TriggerSource (can't read Software)" )
257+ ptr_trigger_source .SetIntValue (int (ptr_inference_ready .GetNumericValue ()))
258+
259+ # 3. Set trigger mode to on
260+ ptr_trigger_mode = PySpin .CEnumerationPtr (nodemap .GetNode ("TriggerMode" ))
261+ if not PySpin .IsReadable (ptr_trigger_mode ) or not PySpin .IsWritable (ptr_trigger_mode ):
262+ raise RuntimeError ("unable to configure TriggerMode (can't read or write TriggerMode)" )
263+ ptr_trigger_on = PySpin .CEnumEntryPtr (ptr_trigger_mode .GetEntryByName ("On" ))
264+ if not PySpin .IsReadable (ptr_trigger_on ):
265+ raise RuntimeError ("unable to query TriggerMode On" )
266+ ptr_trigger_mode .SetIntValue (int (ptr_trigger_on .GetNumericValue ()))
267+
268+ # "NOTE: Blackfly and Flea3 GEV cameras need 1 second delay after trigger mode is turned on"
269+ await asyncio .sleep (1 )
270+
271+ # -- Load filter information --
272+ if self ._filters is None :
273+ await self ._load_filters ()
274+
275+ # -- Load objective information --
276+ if self ._objectives is None :
277+ await self ._load_objectives ()
267278
268279 @property
269280 def version (self ) -> str :
0 commit comments