General camera communication concepts are described on the corresponding page.
Photon Focus pfcam interface¶
Photon Focus CameraLink cameras transfer their data to the PC using frame grabbers (e.g., via NI IMAQ or Silicon Software interfaces). Hence, the camera control is done through the serial port built into the CameraLink interface. However, the cameras use a closed binary protocol, so all the control is done through the pfcam library provided by Photon Focus. It relies on the libraries exposed by the frame grabber manufacturers (e.g., the standard
cl*serial.dll) to communicate with the camera directly, meaning that the pfcam user simply calls its method, and all the communication happens behind the scenes.
In principle, pfcam can work with any frame grabber. Because of that, there are two different kinds of classes for this camera. To start with, there is
.PhotonFocus.IPhotonFocusCamera, which provides interface for addressing camera properties, but can not handle actual frame acquisition. Using this class directly leads to errors in any frame data related methods (e.g.,
read_multiple_images), and it is mostly intended to serve as a base class to be combined with the actual frame grabber. Two such combined classes are already provided:
.PhotonFocus.PhotonFocusIMAQCamera for National Instruments frame grabbers using the NI IMAQ interface,
.PhotonFocus.PhotonFocusSiSoCamera for Silicon Software frame grabbers, and
.PhotonFocus.PhotonFocusBitFlowCamera for BitFlow frame grabbers. All classes are complete and ready to use. In addition to combining camera and frame grabber control, they also implement basic consistency support, such as automatic adjustment of frame grabber ROI and data transfer format.
These cameras require
pfcam.dll, which is installed with freely available (upon registration) PFInstaller. In addition, this DLL requires
comdll.dll and the DLLs referring to a particular camera, e.g.,
mv_d1024e_160.dll. After installation, the path to the DLLs (all located by default in
Photonfocus/PFRemote/bin folder in
Program Files) is automatically added to system
PATH variable, which is one of the places where pylablib looks for it by default. If the DLLs are located elsewhere, the path can be specified using the library parameter
import pylablib as pll pll.par["devices/dlls/pfcam"] = "path/to/dlls" from pylablib.devices import PhotonFocus cam = PhotonFocus.PhotonFocusIMAQCamera()
The camera class requires two pieces of information. First is the frame grabber interface connection, e.g., NI IMAQ interface name (e.g.,
"img0") identified as described in the NI IMAQ documentation, or Silicon Software board and applet described in Silicon Software documentation. The second piece of information is the pfcam port, which is either a number starting from zero indexing the port in the ports list, or a tuple
(manufacturer, port), e.g.,
("National Instruments", "port0"). To list all of the connected pfcam-compatible cameras, you can use the PFRemote software (the interface number is given in parentheses after every connection option in the list) or run
>> from pylablib.devices import PhotonFocus, IMAQ >> IMAQ.list_cameras() # get all IMAQ frame grabber devices ['img0.iid'] >> PhotonFocus.list_cameras() # by default, get only the ports which support pfcam interface [(1, TCameraInfo(manufacturer='National Instruments', port='port0', version=5, type=0))] >> cam = PhotonFocus.PhotonFocus.PhotonFocusIMAQCamera(imaq_name="img0.iid", pfcam_port=("National Instruments", "port0")) >> cam.close() >> cam = PhotonFocus.PhotonFocus.PhotonFocusIMAQCamera(imaq_name="img0.iid", pfcam_port=1) # same effect as above >> cam.close()
The operation of these cameras is relatively standard. They support all the standard methods for dealing with ROI and exposure, starting and stopping acquisition, and operating the frame reading loop. However, there’s a couple of differences from the standard libraries worth highlighting:
The SDK also provides a universal interface for getting and setting various camera attributes (called “properties” in the documentation) using their name. You can use
IPhotonFocusCamera.set_attribute_value()for that, as well as
.cavattribute which gives a dictionary-like access:>> cam = PhotonFocus.PhotonFocusIMAQCamera() >> cam.get_attribute_value("Window/W") # get the ROI width 256 >> cam.set_attribute_value("ExposureTime", 0.1) # set the exposure to 100ms >> cam.cav["ExposureTime"] # get the exposure; could also use cam.get_attribute_value("ExposureTime") 0.1
Some values (e.g.,
Reset) serve as commands; these can be invoked using
PhotonFocusIMAQCamera.call_command()method. To see all available attributes, you can call
IPhotonFocusCamera.get_all_attributes()to get a dictionary with attribute objects, and
IPhotonFocusCamera.get_all_attribute_values()to get the dictionary of attribute values. The attribute objects provide additional information: attribute range, step, and units:>> cam = PhotonFocus.PhotonFocusIMAQCamera() >> attr = cam.get_attribute("Window/W") >> attr.writable True >> (attr.min, attr.max) (16, 1024)
PhotonFocus.PhotonFocusIMAQCamerasupports all of
IMAQ.IMAQCamerafeatures, such as trigger control and fast buffer acquisition. Some methods have been modified to make them more convenient: e.g.,
PhotonFocusIMAQCamera.set_roi()method sets the camera ROI and automatically adjusts the frame grabber ROI to match.
Same is true for
PhotonFocus.PhotonFocusSiSoCamera, which, e.g., provides access to all of the frame grabber variables.
The camera supports a status line, which replaces the bottom one or two rows of the frame with encoded frame-related data such as frame number and timestamp. You can use
PhotonFocus.get_status_lines()function to identify and extract the data in the status lines from the supplied frames. In addition, you can use
PhotonFocus.remove_status_line()to remove the status lines in several possible ways: zeroing out, masking with the previous frame, cutting off entirely, etc.
If several PhotonFocus cameras are connected, you need to correctly associate different PFCam ports with the corresponding frame grabbers. To do that, you can use the function