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.