Skip to content

NodeMapInfo_QuickSpin


# coding=utf-8
# =============================================================================
# Copyright (c) 2026 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved.
#
# This software is the confidential and proprietary information of FLIR
# Integrated Imaging Solutions, Inc. ("Confidential Information"). You
# shall not disclose such Confidential Information and shall use it only in
# accordance with the terms of the license agreement you entered into
# with FLIR Integrated Imaging Solutions, Inc. (FLIR).
#
# FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
# SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES
# SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
# THIS SOFTWARE OR ITS DERIVATIVES.
# =============================================================================
#
# NodeMapInfo_QuickSpin.py shows how to interact with nodes
# using the QuickSpin API. QuickSpin is a subset of the Spinnaker library
# that allows for simpler node access and control.
#
# This example demonstrates the retrieval of information from both the
# transport layer and the camera. Because the focus of this example is node
# access, which is where QuickSpin and regular Spinnaker differ, this
# example differs from NodeMapInfo quite a bit.
#
# A much wider range of topics is covered in the full Spinnaker examples than
# in the QuickSpin ones. There are only enough QuickSpin examples to
# demonstrate node access and to get started with the API; please see full
# Spinnaker examples for further or specific knowledge on a topic.
#
# Please leave us feedback at: https://www.surveymonkey.com/r/TDYMVAPI
# More source code examples at: https://github.com/Teledyne-MV/Spinnaker-Examples
# Need help? Check out our forum at: https://teledynevisionsolutions.zendesk.com/hc/en-us/community/topics

import PySpin
import sys


def print_node_info(node):
    """
    Prints node information if applicable

    *** NOTES ***
    Notice that each node is checked for availablility and readability prior
    to value retrieval. Checking for availability and readability (or writability
    when applicable) whenever a node is accessed is important in terms of error
    handling. If a node retrieval error occurs but remains unhandled, an exception
    is thrown.

    :param node: Node to get information from.
    :type node: INode
    """
    if node is not None and PySpin.IsReadable(node):
        print(PySpin.CValuePtr(node).ToString())
    else:
        print('unavailable')


def print_transport_layer_device_info(cam):
    """
    Prints device information from the transport layer.

    *** NOTES ***
    In QuickSpin, accessing device information on the transport layer is
    accomplished via a camera's TLDevice property. The TLDevice property
    houses nodes related to general device information such as the three
    demonstrated below, device access status, XML and GUI paths and
    locations, and GEV information to name a few. The TLDevice property
    allows access to nodes that would generally be retrieved through the
    TL device nodemap in full Spinnaker.

    Notice that each node is checked for availability and readability
    prior to value retrieval. Checking for availability and readability
    (or writability when applicable) whenever a node is accessed is
    important in terms of error handling. If a node retrieval error
    occurs but remains unhandled, an exception is thrown.

    :param cam: Camera to get information from.
    :type cam: CameraPtr
    :return: True if successful, False otherwise.
    :rtype: bool
    """
    try:
        result = True

        # Print device serial number
        print('Device serial number: ', end='')
        print_node_info(cam.TLDevice.DeviceSerialNumber)

        # Print device vendor name
        #
        # *** NOTE ***
        # To check node readability/writability, you can either
        # compare its access mode with RO, RW, etc. or you can use
        # the IsReadable/IsWritable functions on the node.
        print('Device vendor name: ', end='')
        print_node_info(cam.TLDevice.DeviceVendorName)

        # Print device display name
        print('Device display name: ', end='')
        print_node_info(cam.TLDevice.DeviceDisplayName)

    except PySpin.SpinnakerException as ex:
        print('Error: %s' % ex)
        return False

    return result


def print_transport_layer_stream_info(cam):
    """
    Prints stream information from transport layer.

    *** NOTES ***
    In QuickSpin, accessing stream information on the transport layer is
    accomplished via a camera's TLStream property. The TLStream property
    houses nodes related to streaming such as the two demonstrated below,
    buffer information, and GEV packet information to name a few. The
    TLStream property allows access to nodes that would generally be
    retrieved through the TL stream nodemap in full Spinnaker.

    :param cam: Camera to get information from.
    :type cam: CameraPtr
    :return: True if successful, False otherwise.
    :rtype: bool
    """
    try:
        result = True

        # Print stream ID
        print('Stream ID: ', end='')
        print_node_info(cam.TLStream.StreamID)

        # Print stream type
        print('Stream type: ', end='')
        print_node_info(cam.TLStream.StreamType)

    except PySpin.SpinnakerException as ex:
        print('Error: %s' % ex)
        return False

    return result


def print_transport_layer_interface_info(interface):
    """
    Prints stream information from the transport layer.

    *** NOTES ***
    In QuickSpin, accessing interface information is accomplished via an
    interface's TLInterface property. The TLInterface property houses
    nodes that hold information about the interface such as the three
    demonstrated below, other general interface information, and
    GEV addressing information. The TLInterface property allows access to
    nodes that would generally be retrieved through the interface nodemap
    in full Spinnaker.

    Interface nodes should also always be checked for availability and
    readability (or writability when applicable). If a node retrieval
    error occurs but remains unhandled, an exception is thrown.

    :param interface: Interface to get information from.
    :type interface: InterfacePtr
    :return: True if successful, False otherwise.
    :rtype: bool
    """
    try:
        result = True

        # Print interface display name
        print('Interface display name: ', end='')
        print_node_info(interface.TLInterface.InterfaceDisplayName)

        # Print interface ID
        print('Interface ID: ', end='')
        print_node_info(interface.TLInterface.InterfaceID)

        # Print interface type
        print('Interface type: ', end='')
        print_node_info(interface.TLInterface.InterfaceType)

        """
        Print information specific to the interface's host adapter from 
        the transport layer

        *** NOTES ***
        This information can help in determining which interface to use
        for better performance as some host adapters may have more
        significant physical limitations.

        Interface nodes should also always be checked for availability
        readability (or writability when applicable). If a node retrieval
        error occurs but remains unhandled, an exception is thrown.
        """
        # Print host adapter name
        print('Host adapter name: ', end='')
        print_node_info(interface.TLInterface.HostAdapterName)

        # Print host adapter vendor name
        print('Host adapter vendor: ', end='')
        print_node_info(interface.TLInterface.HostAdapterVendor)

        # Print host adapter driver version
        print('Host adapter driver version: ', end='')
        print_node_info(interface.TLInterface.HostAdapterDriverVersion)

        print()
    except PySpin.SpinnakerException as ex:
        print('Error: %s' % ex)
        return False

    return result


def print_genicam_device_info(cam):
    """
    Prints device information from the camera.

    *** NOTES ***
    Most camera interaction happens through GenICam nodes. The
    advantages of these nodes is that there is a lot more of them, they
    allow for a much deeper level of interaction with a camera, and no
    intermediate property (i.e. TLDevice or TLStream) is required. The
    disadvantage is that they require initialization.

    :param cam: Camera to get information from.
    :type cam: CameraPtr
    :return: True if successful, False otherwise.
    :rtype: bool
    """
    try:
        result = True

        # Print exposure time
        print('Exposure time: ', end='')
        print_node_info(cam.ExposureTime)

        # Print black level
        print('Black level: ', end='')
        print_node_info(cam.BlackLevel)

        # Print height
        print('Height: ', end='')
        print_node_info(cam.Height)

    except PySpin.SpinnakerException as ex:
        print('Error: %s' % ex)
        return False

    return result


def main():
    """
    Example entry point; this function prints transport layer information from
    each interface and transport and GenICam information from each camera.

    :return: True if successful, False otherwise.
    :rtype: bool
    """
    result = True

    # Retrieve singleton reference to system object
    sys = PySpin.System.GetInstance()

    # Get current library version
    version = sys.GetLibraryVersion()
    print('Library version: %d.%d.%d.%d' % (version.major, version.minor, version.type, version.build))

    # Retrieve list of cameras from the system
    cam_list = sys.GetCameras()

    num_cams = cam_list.GetSize()

    print('Number of cameras detected: %i \n' % num_cams)

    # Finish if there are no cameras
    if num_cams == 0:
        # Clear camera list before releasing system
        cam_list.Clear()

        # Release system instance
        sys.ReleaseInstance()

        print('Not enough cameras!')
        input('Done! Press Enter to exit...')
        return False

    # Retrieve list of interfaces from the system 
    iface_list = sys.GetInterfaces()

    num_ifaces = iface_list.GetSize()

    print('Number of interfaces detected: %i \n' % num_ifaces)

    # Print information on each interface
    #
    # *** NOTES ***
    # All USB 3 Vision and GigE Vision interfaces should enumerate for
    # Spinnaker.
    print('\n*** PRINTING INTERFACE INFORMATION ***\n')

    for iface in iface_list:
        result &= print_transport_layer_interface_info(iface)

    # Release reference to interface
    # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically
    # cleaned up when going out of scope.
    # The usage of del is preferred to assigning the variable to None.
    del iface

    # Print general device information on each camera from transport layer
    #
    # *** NOTES ***
    # Transport layer nodes do not require initialization in order to interact
    # with them.
    print('\n*** PRINTING TRANSPORT LAYER DEVICE INFORMATION ***\n')

    for cam in cam_list:
        result &= print_transport_layer_device_info(cam)

    # Print streaming information on each camera from transport layer
    #
    # *** NOTES ***
    # Again, initialization is not required to print information from the
    # transport layer; this is equally true of streaming information.
    print('\n*** PRINTING TRANSPORT LAYER STREAMING INFORMATION ***\n')

    for cam in cam_list:
        result &= print_transport_layer_stream_info(cam)

    # Print device information on each camera from GenICam nodemap
    #
    # *** NOTES ***
    # GenICam nodes require initialization in order to interact with
    # them; as such, this loop initializes the camera, prints some information
    # from the GenICam nodemap, and then deinitializes it. If the camera were
    # not initialized, node availability would fail.
    print('\n*** PRINTING GENICAM INFORMATION ***\n')

    for cam in cam_list:
        # Initialize camera
        cam.Init()

        # Print info
        result &= print_genicam_device_info(cam)

        # Deinitialize camera
        cam.DeInit()

    # Release reference to camera
    # NOTE: Unlike the C++ examples, we cannot rely on pointer objects being automatically
    # cleaned up when going out of scope.
    # The usage of del is preferred to assigning the variable to None.
    del cam

    # Clear camera list before releasing system
    cam_list.Clear()

    # Clear interface list before releasing system
    iface_list.Clear()

    # Release system instance
    sys.ReleaseInstance()

    input('\nDone! Press Enter to exit...')
    return result

if __name__ == '__main__':
    if main():
        sys.exit(0)
    else:
        sys.exit(1)