Handling GenTL Module Objects¶
The following class diagram shows relationship between the Python classes those are provided as Python package gentl.py
. In this section, we will learn how to manipulate those classes in Python code.
The following import statements are required for this tutorial.
from genicam.gentl import DEVICE_ACCESS_FLAGS_LIST
from genicam.gentl import GenTLProducer, Port
from genicam.gentl import ClosedException, InvalidHandleException
from genicam.genapi import NodeMap, AbstractPort, EAccessMode
And prepare a path name to the target CTI file as follow. We use TLSimu as a target GenTL Producer for this tutorial.
import os
import sys
path_name = os.path.join('C:/Projects/genicam', 'bin', 'Win64_x64', 'TLSimu.cti')
First, instantiate a GenTLProducer
object calling create_producer()
method:
producer = GenTLProducer.create_producer()
Then open a CTI file calling open()
method:
producer.open(path_name)
Having called the open()
method, the GenTLProducer
object will open the specified CTI file and eventually call GCInitLib()
function internally. It will allow you to use the funtionality that the target GenTL Producer provides.
Next, instantiate a System
object calling create_system()
method:
system = producer.create_system()
Then open the GenTL System module calling open()
method:
system.open()
To instantiate an Interface
object, now you have to update the interface information list first that the System
object is holding calling update_interface_info_list()
method:
system.update_interface_info_list(1000)
Here you can instantiate an Interface
object supplying an index to InterfaceInfo
object calling create_interface()
method:
interface = system.interface_info_list[0].create_interface()
And open the GenTL Interface module calling open()
method:
interface.open()
By the way, you can get the number of items in the property using Python’s built-in len()
function. You can apply this trick to other information list
properties.
num_of_interfaces = len(system.interface_info_list)
Next, we instantiate a Device
object. To instantiate a Device
object you have to update the device information list that the Interface
object is holding calling update_device_info_list()
method:
interface.update_device_info_list(1000)
Here you can instantiate a Device
object calling create_device()
method:
device = interface.device_info_list[0].create_device()
And open the GenTL Device module calling open()
method. You can specify either access mode from DEVICE_ACCESS_FLAGS_LIST
:
device.open(
DEVICE_ACCESS_FLAGS_LIST.DEVICE_ACCESS_EXCLUSIVE
)
Finally, we instantiate a NodeMap
object defined by genapi
module that is out of scope of this documentation. In general, when we use a NodeMap
object, we connect a remote device’s port to the NodeMap
object. To connect a port to a NodeMap
object, we call connect()
method of the NodeMap
object. The method takes a class that is derived from AbstractPort
class which is also defined by genapi
module. So now we define own concrete port class deriving from AbstractPort
class here.
class ConcretePort(AbstractPort):
def __init__(self, gentl_port=None):
super().__init__()
self._assign_port_impl(gentl_port)
def is_open(self):
return False if self._gentl_port is None else True
def write(self, address, value):
self._gentl_port.write(address, value)
def read(self, address, length):
buffer = self._gentl_port.read(address, length)
return buffer[1]
def open(self, gentl_port_obj):
self._assign_port_impl(gentl_port_obj)
def close(self):
self._gentl_port = None
def get_access_mode(self):
return EAccessMode.RW if self.is_open else EAccessMode.NA
def _assign_port_impl(self, obj):
# Check if the object is a GenTL Port module object.
if isinstance(obj, Port):
self._gentl_port = obj
else:
raise TypeError('Supplied object is not a GenTL Port object.')
And we instantiate a ConcretePort
object. By design, its constructor takes a Port
object that is defined by the gentl
module as the parameter and now we want to instantiate it with our remote device’s port so we pass the Port
object that is returned by remote_port
attribute of the Device
object:
concrete_port = ConcretePort(device.remote_port)
Next, download a GenICam device description file from the remote device. First, let check where the file is located:
# Expected format: 'Local:DIDEV.xml;300;38a4'
url = device.remote_port.url_info_list[0].url
Then parse it:
location, others = url.split(':', 1)
file_name, address, size = others.split(';')
address = int(address, 16)
size = int(size, 16)
Now we’re ready for downloading the device description file. Having called the following code, you will get the content of a GenICam device description file:
file_content = device.remote_port.read(address, size)
The read()
method our port class object returns a Python’s builit-in list
objoect that is consisting of a Python’s built-in bytes
object which holds the read out data and an int
object to represents the size of the read out data. Now we need the read out data itself so we get that accessing index #1 of the returned object. If you need the size, use index #0.
ddf = file_content[1]
Here we instantiate a NodeMap
object and load the downloaded device description file content on it.
node_map = NodeMap()
node_map.load_xml_from_string(ddf)
And we only have the last step. Let’s connect the remote port to the node map object so that GenApi can interact with the remote device. The connect()
method of NodeMap
class takes a port class object which derives from AbstractPort
class of genapi
module and a str
object that holds the name of the port.
node_map.connect(concrete_port, device.remote_port.name)
Okay, now you have finished the minimum preparation for the following possible manipulations. Regarding image acquisition that involves DataStream
class, Buffer
class and an event manager class, you will learn about it in the following chapter.
Releasing External Resources¶
Managing external resource is very important. In this section we learn about external resource management.
Python manages objects’ lifetime using reference count. When the reference count reaches to zero, the __del__()
method is called then the object is destructed.
However, even though the GenTL-Pyton Binding has been designed to release the external resources such as a CTI file when it’s destructed but there are cases where reference count doesn’t reach to zero by some reasons so you should not expect the __del__()
method is called in any case to realse external resources.
Having that fact, you should explicitly release the external resources calling its close()
method:
producer.close()
Or using with
statement is another way to go:
with GenTLProducer.create_producer() as producer:
producer.open(path_name)
system = producer.create_system()
Using with
statement we can be sure that the GenTLProducer
object will release the external resources once it goes out of the scope. It gives you the same effect with calling the close()
method.
Anyway, leaving hooked external resources is not good thing at all so please carefylly consider a way to release the external resources for sure.