2727PyCapture2 = None
2828
2929class FlyCapture2_Camera (object ):
30+ """The backend hardware interface class for the FlyCapture2Camera.
31+
32+ This class handles all of the API/hardware implementation details for the
33+ corresponding labscript device. It is used by the BLACS worker to send
34+ appropriate API commands to the camera for the standard BLACS camera operations
35+ (i.e. transition_to_buffered, get_attributes, snap, etc).
36+
37+ Attributes:
38+ camera (PyCapture2.Camera): Handle to connected camera.
39+ get_props (list): This list sets which values of each property object
40+ are returned when queried by :obj:`get_attribute`.
41+ pixel_formats (IntEnum): An IntEnum object that is automatically
42+ populated with the supported pixel types of the connected camera.
43+ width (int): Width of images for most recent acquisition.
44+ Used by :obj:`_decode_image_data` to format images correctly.
45+ height (int): Height of images for most recent acquisition.
46+ Used by :obj:`_decode_image_data` to format images correctly.
47+ pixelFormat (str): Pixel format name for most recent acquisition.
48+ Used by :obj:`_decode_image_data` to format images correctly.
49+ _abort_acquisition (bool): Abort flag that is polled during buffered
50+ acquisitions.
51+ """
3052 def __init__ (self , serial_number ):
3153 """Initialize FlyCapture2 API camera.
3254
33- Serial number should be of int type."""
55+ Searches all cameras reachable by the host using the provided serial
56+ number. Fails with API error if camera not found.
57+
58+ This function also does a significant amount of default configuration.
59+
60+ * It defaults the grab timeout to 1 s
61+ * Ensures use of the API's HighPerformanceRetrieveBuffer
62+ * Ensures the camera is in Format 7, Mode 0 with full frame readout and MONO8 pixels
63+ * If using a GigE camera, automatically maximizes the packet size and warns if Jumbo packets are not enabled on the NIC
64+
65+ Args:
66+ serial_number (int): serial number of camera to connect to
67+ """
3468
3569 global PyCapture2
3670 import PyCapture2
@@ -109,12 +143,16 @@ def __init__(self, serial_number):
109143
110144 def set_attributes (self , attr_dict ):
111145 """Sets all attribues in attr_dict.
146+
112147 FlyCapture does not control all settings through same interface,
113148 so we must do them separately.
114- Interfaces are: {
115- <Standard PROPERTY_TYPE>,
116- 'TriggerMode',
117- 'ImageMode'}
149+ Interfaces are: <Standard PROPERTY_TYPE>, TriggerMode, ImageMode
150+
151+ Args:
152+ attr_dict (dict): dictionary of property dictionaries to set for the camera.
153+ These property dictionaries assume a specific structure, outlined in
154+ :obj:`set_attribute`, :obj:`set_trigger_mode` and , :obj:`set_image_mode`
155+ methods.
118156 """
119157
120158 for prop , vals in attr_dict .items ():
@@ -128,7 +166,17 @@ def set_attributes(self, attr_dict):
128166 self .set_attribute (prop , vals )
129167
130168 def set_trigger_mode (self ,trig_dict ):
131- """Configures triggering options via Trigger Mode interface."""
169+ """Configures triggering options via Trigger Mode interface.
170+
171+ Args:
172+ trig_dict (dict): dictionary with trigger mode property settings. Allowed keys:
173+
174+ * 'onOff': bool
175+ * 'polarity': 0,1
176+ * 'source': int
177+ * 'mode': int
178+
179+ """
132180 trig_mode = self .camera .getTriggerMode ()
133181 for k ,v in trig_dict .items ():
134182 setattr (trig_mode ,k ,v )
@@ -140,7 +188,17 @@ def set_trigger_mode(self,trig_dict):
140188 raise Exception (msg ) from e
141189
142190 def set_image_mode (self ,image_settings ):
143- """Configures ROI and image control via Format 7, Mode 0 interface."""
191+ """Configures ROI and image control via Format 7, Mode 0 interface.
192+
193+ Args:
194+ image_settings (dict): dictionary of image settings. Allowed keys:
195+
196+ * 'pixelFormat': valid pixel format string, i.e. 'MONO8'
197+ * 'offsetX': int
198+ * 'offsetY': int
199+ * 'width': int
200+ * 'height': int
201+ """
144202 image_info , supported = self .camera .getFormat7Info (0 )
145203 Hstep = image_info .offsetHStepSize
146204 Vstep = image_info .offsetVStepSize
@@ -177,13 +235,23 @@ def set_image_mode(self,image_settings):
177235
178236 def set_attribute (self , name , values ):
179237 """Set the values of the attribute of the given name using the provided
180- dictionary values. Typical structure is:
181- values = {'onOff':True,
182- 'autoManualMode':False,
183- 'absControl':True,
184- 'absValue':0.0}
238+ dictionary values.
185239
186- Note that invalid settings tend to coerce instead of error."""
240+ Generally, absControl should be used to configure settings. Note that
241+ invalid settings tend to coerce instead of presenting an error.
242+
243+ Args:
244+ name (str):
245+ values (dict): Dictionary of settings for the property. Allowed keys are:
246+
247+ * 'onOff': bool
248+ * 'autoManualMode': bool
249+ * 'absControl': bool
250+ * 'absValue': float
251+ * 'valueA': int
252+ * 'valueB': int
253+ * 'onePush': bool
254+ """
187255 try :
188256 prop = self .camera .getProperty (getattr (PyCapture2 .PROPERTY_TYPE ,name ))
189257
@@ -198,10 +266,12 @@ def set_attribute(self, name, values):
198266 def get_attributes (self , visibility_level , writeable_only = True ):
199267 """Return a nested dict of all readable attributes.
200268
201- Structure is of form: {
202- <Standard PROPERTY_TYPE>:{},
203- 'TriggerMode':{},
204- 'ImageMode':{}}
269+ Args:
270+ visibility_level (str): Not used.
271+ writeable_only (:obj:`bool`, optional): Not used
272+
273+ Returns:
274+ dict: Dictionary of property dictionaries
205275 """
206276 props = {}
207277 prop_names = {prop for prop in dir (PyCapture2 .PROPERTY_TYPE )
@@ -233,7 +303,15 @@ def get_attributes(self, visibility_level, writeable_only=True):
233303 return props
234304
235305 def get_attribute (self , name ):
236- """Return current values dictionary of attribute of the given name"""
306+ """Return current values dictionary of attribute of the given name.
307+
308+ Args:
309+ name (str): Property name to read
310+
311+ Returns:
312+ dict: Dictionary of property values with structure as defined in
313+ :obj:`set_attribute`.
314+ """
237315 try :
238316 prop_dict = {}
239317 prop = self .camera .getProperty (getattr (PyCapture2 .PROPERTY_TYPE ,name ))
@@ -245,7 +323,11 @@ def get_attribute(self, name):
245323 raise Exception (f"Failed to get attribute { name } " ) from e
246324
247325 def snap (self ):
248- """Acquire a single image and return it"""
326+ """Acquire a single image and return it
327+
328+ Returns:
329+ numpy.array: Acquired image
330+ """
249331
250332 self .configure_acquisition (continuous = False ,bufferCount = 1 )
251333 image = self .grab ()
@@ -254,9 +336,17 @@ def snap(self):
254336
255337 def configure_acquisition (self , continuous = True , bufferCount = 10 ):
256338 """Configure acquisition buffer count and grab mode.
257- Continuous mode only keeps most recent frames. Else, keep all frames.
258339
259- Also get returned image parameters for formatting purposes.
340+ This method also saves image width, heigh, and pixelFormat to class
341+ attributes for returned image formatting.
342+
343+ Args:
344+ continuous (:obj:`bool`, optional): If True, camera will continuously
345+ acquire and only keep most recent frames in the buffer. If False,
346+ all acquired frames are kept and error occurs if buffer is exceeded.
347+ Default is True.
348+ bufferCount (:obj:`int`, optional): Number of memory buffers to use
349+ in the acquistion. Default is 10.
260350 """
261351 config = self .camera .getConfiguration ()
262352 config .numBuffers = bufferCount
@@ -276,7 +366,11 @@ def configure_acquisition(self, continuous=True, bufferCount=10):
276366 self .camera .startCapture ()
277367
278368 def grab (self ):
279- """Grab and return single image during pre-configured acquisition."""
369+ """Grab and return single image during pre-configured acquisition.
370+
371+ Returns:
372+ numpy.array: Returns formatted image
373+ """
280374
281375 result = self .camera .retrieveBuffer ()
282376
@@ -286,7 +380,16 @@ def grab(self):
286380 return self ._decode_image_data (img )
287381
288382 def grab_multiple (self , n_images , images ):
289- """Grab n_images into images array during buffered acquistion."""
383+ """Grab n_images into images array during buffered acquistion.
384+
385+ Grab method involves a continuous loop with fast timeout in order to
386+ poll :obj:`_abort_acquisition` for a signal to abort.
387+
388+ Args:
389+ n_images (int): Number of images to acquire. Should be same number
390+ as the bufferCount in :obj:`configure_acquisition`.
391+ images (list): List that images will be saved to as they are acquired
392+ """
290393 print (f"Attempting to grab { n_images } images." )
291394 for i in range (n_images ):
292395 while True :
@@ -304,9 +407,19 @@ def grab_multiple(self, n_images, images):
304407 print (f"Got { len (images )} of { n_images } images." )
305408
306409 def _decode_image_data (self ,img ):
307- """FlyCapture2 image buffers require significant formatting.
410+ """Formats returned FlyCapture2 API image buffers.
411+
412+ FlyCapture2 image buffers require significant formatting.
308413 This returns what one would expect from a camera.
309- configure_acquisition must be called first to set image format parameters."""
414+ :obj:`configure_acquisition` must be called first to set image format parameters.
415+
416+ Args:
417+ img (numpy.array): A 1-D array image buffer of uint8 values to format
418+
419+ Returns:
420+ numpy.array: Formatted array based on :obj:`width`, :obj:`height`,
421+ and :obj:`pixelFormat`.
422+ """
310423 pix_fmt = self .pixelFormat
311424 if pix_fmt .startswith ('MONO' ):
312425 if pix_fmt .endswith ('8' ):
@@ -322,7 +435,12 @@ def _decode_image_data(self,img):
322435 return image .copy ()
323436
324437 def _send_format7_config (self ,image_config ):
325- """Validates and sends the Format7 configuration packet."""
438+ """Validates and sends the Format7 configuration packet.
439+
440+ Args:
441+ image_config (PyCapture2.Format7ImageSettings): Format7ImageSettings
442+ object to validate and send to camera.
443+ """
326444 try :
327445 fmt7PktInfo , valid = self .camera .validateFormat7Settings (image_config )
328446 if valid :
@@ -331,25 +449,33 @@ def _send_format7_config(self,image_config):
331449 raise RuntimeError ('Error configuring image settings' ) from e
332450
333451 def stop_acquisition (self ):
452+ """Tells camera to stop current acquistion."""
334453 self .camera .stopCapture ()
335454
336455 def abort_acquisition (self ):
456+ """Sets :obj:`_abort_acquisition` flag to break buffered acquisition loop."""
337457 self ._abort_acquisition = True
338458
339459 def close (self ):
460+ """Closes :obj:`camera` handle to the camera."""
340461 self .camera .disconnect ()
341462
342463
343464class FlyCapture2CameraWorker (IMAQdxCameraWorker ):
344465 """FlyCapture2 API Camera Worker.
345466
346- Inherits from IMAQdxCameraWorker. Overloads get_attributes_as_dict
347- to use FlyCapture2Camera.get_attributes() method."""
467+ Inherits from obj:` IMAQdxCameraWorker`. Defines :obj:`interface_class` and overloads
468+ :obj:`get_attributes_as_dict` to use FlyCapture2Camera.get_attributes() method."""
348469 interface_class = FlyCapture2_Camera
349470
350471 def get_attributes_as_dict (self , visibility_level ):
351472 """Return a dict of the attributes of the camera for the given visibility
352- level"""
473+ level
474+
475+ Args:
476+ visibility_level (str): Normally configures level of attribute detail
477+ to return. Is not used by FlyCapture2_Camera.
478+ """
353479 if self .mock :
354480 return IMAQdxCameraWorker .get_attributes_as_dict (self ,visibility_level )
355481 else :
0 commit comments