From 2ac23b2510d4083beb9e21beed689b41a09a7557 Mon Sep 17 00:00:00 2001 From: morefigs Date: Mon, 21 Jan 2019 15:28:06 +1100 Subject: added simple usage examples --- .gitignore | 2 ++ examples/check_version.py | 7 +++++++ examples/list_cameras.py | 12 ++++++++++++ tests/__init__.py | 0 4 files changed, 21 insertions(+) create mode 100644 examples/check_version.py create mode 100644 examples/list_cameras.py delete mode 100644 tests/__init__.py diff --git a/.gitignore b/.gitignore index 692ad13..8448e35 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,5 @@ nosetests.xml # PyCharm .idea/ .cache/ + +venv* \ No newline at end of file diff --git a/examples/check_version.py b/examples/check_version.py new file mode 100644 index 0000000..de8449c --- /dev/null +++ b/examples/check_version.py @@ -0,0 +1,7 @@ +from pymba.vimba import Vimba + + +if __name__ == '__main__': + + vmb = Vimba() + print(vmb.version) diff --git a/examples/list_cameras.py b/examples/list_cameras.py new file mode 100644 index 0000000..0be2e12 --- /dev/null +++ b/examples/list_cameras.py @@ -0,0 +1,12 @@ +from pymba.vimba import Vimba +from time import sleep + + +if __name__ == '__main__': + + with Vimba() as vmb: + # required for discovering GigE cameras + if vmb.system.GeVTLIsPresent: + vmb.system.runFeatureCommand("GeVDiscoveryAllOnce") + sleep(0.2) + print(vmb.camera_ids) diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 -- cgit v1.2.3 From 1ab00911d6c898e63301bc458757b47d8fe8c115 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 13:39:24 +1100 Subject: clean up C function and structure definitions --- pymba/vimba_c.py | 445 ++++++++++++++++++++++++++++++++++++++++++ pymba/vimba_dll.py | 489 ----------------------------------------------- pymba/vimba_structure.py | 106 ---------- 3 files changed, 445 insertions(+), 595 deletions(-) create mode 100644 pymba/vimba_c.py delete mode 100644 pymba/vimba_dll.py delete mode 100644 pymba/vimba_structure.py diff --git a/pymba/vimba_c.py b/pymba/vimba_c.py new file mode 100644 index 0000000..5ddc5c0 --- /dev/null +++ b/pymba/vimba_c.py @@ -0,0 +1,445 @@ +from sys import platform as sys_plat +import platform +import os +from ctypes import * + +from .vimba_exception import VimbaException + + +if sys_plat == "win32": + + def find_win_dll(arch): + """ Finds the highest versioned windows dll for the specified architecture. """ + bases = [ + r'C:\Program Files\Allied Vision Technologies\AVTVimba_%i.%i\VimbaC\Bin\Win%i\VimbaC.dll', + r'C:\Program Files\Allied Vision\Vimba_%i.%i\VimbaC\Bin\Win%i\VimbaC.dll' + ] + dlls = [] + for base in bases: + for major in range(3): + for minor in range(10): + candidate = base % (major, minor, arch) + if os.path.isfile(candidate): + dlls.append(candidate) + if not dlls: + if 'VIMBA_HOME' in os.environ: + candidate = os.environ ['VIMBA_HOME'] + '\VimbaC\Bin\Win%i\VimbaC.dll' % (arch) + if os.path.isfile(candidate): + dlls.append(candidate) + if not dlls: + raise IOError("VimbaC.dll not found.") + return dlls[-1] + + if '64' in platform.architecture()[0]: + vimbaC_path = find_win_dll(64) + else: + vimbaC_path = find_win_dll(32) + dll_loader = windll + +else: + dll_loader = cdll + + if 'x86_64' in os.uname()[4]: + assert os.environ.get( + "GENICAM_GENTL64_PATH"), "you need your GENICAM_GENTL64_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" + tlPath = [p for p in os.environ.get("GENICAM_GENTL64_PATH").split(":") if p][0] + vimba_dir = "/".join(tlPath.split("/")[1:-3]) + vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/x86_64bit/libVimbaC.so" + elif 'x86_32' in os.uname()[4]: + print("Warning: x86_32 reached!") + assert os.environ.get( + "GENICAM_GENTL32_PATH"), "you need your GENICAM_GENTL32_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" + tlPath = [p for p in os.environ.get("GENICAM_GENTL32_PATH").split(":") if p][0] + vimba_dir = "/".join(tlPath.split("/")[1:-3]) + vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/x86_32bit/libVimbaC.so" + elif 'arm' in os.uname()[4]: + assert os.environ.get( + "GENICAM_GENTL32_PATH"), "you need your GENICAM_GENTL32_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" + tlPath = [p for p in os.environ.get("GENICAM_GENTL32_PATH").split(":") if p][0] + vimba_dir = "/".join(tlPath.split("/")[1:-3]) + vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/arm_32bit/libVimbaC.so" + elif 'aarch64' in os.uname()[4]: + assert os.environ.get( + "GENICAM_GENTL64_PATH"), "you need your GENICAM_GENTL64_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" + tlPath = [p for p in os.environ.get("GENICAM_GENTL64_PATH").split(":") if p][0] + vimba_dir = "/".join(tlPath.split("/")[1:-3]) + vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/arm_64bit/libVimbaC.so" + else: + raise ValueError("Pymba currently doesn't support %s" % os.uname()[4]) + + +# Callback function type +if sys_plat == "win32": + CALLBACK_FUNCTYPE = WINFUNCTYPE +else: + CALLBACK_FUNCTYPE = CFUNCTYPE + + +class MemoryBlock: + """ + A memory block object for dealing neatly with C memory allocations. + """ + + @property + def block(self): + return c_void_p(addressof(self._block)) + + def __init__(self, block_size): + self._block = create_string_buffer(block_size) + + # this seems to be None if too much memory is requested + if self._block is None: + raise VimbaException(-51) + + def __del__(self): + del self._block + + +class VmbVersionInfo(Structure): + _fields_ = [ + ('major', c_uint32), + ('minor', c_uint32), + ('patch', c_uint32)] + + +class VmbCameraInfo(Structure): + _fields_ = [ + # Unique identifier for each camera + ('cameraIdString', c_char_p), + # Name of the camera + ('cameraName', c_char_p), + # Model name + ('modelName', c_char_p), + # Serial number + ('serialString', c_char_p), + # Used access mode, see VmbAccessModeType + ('permittedAccess', c_uint32), + # Unique value for each interface or bus + ('interfaceIdString', c_char_p)] + + +class VmbFeatureInfo(Structure): + _fields_ = [ + ('name', c_char_p), + ('featureDataType', c_uint32), + ('featureFlags', c_uint32), + ('category', c_char_p), + ('displayName', c_char_p), + ('pollingTime', c_uint32), + ('unit', c_char_p), + ('representation', c_char_p), + ('visibility', c_uint32), + ('tooltip', c_char_p), + ('description', c_char_p), + ('sfncNamespace', c_char_p), + ('isStreamable', c_bool), + ('hasAffectedFeatures', c_bool), + ('hasSelectedFeatures', c_bool)] + + +class VmbFrame(Structure): + _fields_ = [ + # ---- IN ---- + # Comprises image and ancillary data + ('buffer', c_void_p), + # Size of the data buffer + ('bufferSize', c_uint32), + + # User context filled during queuing + ('context', c_void_p * 4), + + # ---- OUT ---- + # Resulting status of the receive operation + ('receiveStatus', c_int32), + # Resulting flags of the receive operation + ('receiveFlags', c_uint32), + + # Size of the image data inside the data buffer + ('imageSize', c_uint32), + # Size of the ancillary data inside the data buffer + ('ancillarySize', c_uint32), + + # Pixel format of the image + ('pixelFormat', c_uint32), + + # Width of an image + ('width', c_uint32), + # Height of an image + ('height', c_uint32), + # Horizontal offset of an image + ('offsetX', c_uint32), + # Vertical offset of an image + ('offsetY', c_uint32), + + # Unique ID of this frame in this stream + ('frameID', c_uint64), + # Timestamp of the data transfer + ('timestamp', c_uint64)] + + +class VmbInterfaceInfo(Structure): + _fields_ = [ + # Unique identifier for each interface + ('interfaceIdString', c_char_p), + # Interface type, see VmbInterfaceType + ('interfaceType', c_uint32), + # Interface name, given by the transport layer + ('interfaceName', c_char_p), + # Serial number + ('serialString', c_char_p), + # Used access mode, see VmbAccessModeType + ('permittedAccess', c_uint32)] + + +_vimba_lib = dll_loader.LoadLibrary(vimbaC_path) + +# ----- The below function signatures are defined in VimbaC.h ----- + +# callback for frame queue +vmb_frame_callback = CALLBACK_FUNCTYPE(c_void_p, + c_void_p, + POINTER(VmbFrame)) + +vmb_version_query = _vimba_lib.VmbVersionQuery +vmb_version_query.restype = c_int32 +vmb_version_query.argtypes = (POINTER(VmbVersionInfo), + c_uint32) + +vmb_startup = _vimba_lib.VmbStartup +vmb_startup.restype = c_int32 + +vmb_shutdown = _vimba_lib.VmbShutdown + +vmb_cameras_list = _vimba_lib.VmbCamerasList +vmb_cameras_list.restype = c_int32 +vmb_cameras_list.argtypes = (POINTER(VmbCameraInfo), + c_uint32, + POINTER(c_uint32), + c_uint32) + +vmb_camera_info_query = _vimba_lib.VmbCameraInfoQuery +vmb_camera_info_query.restype = c_int32 +vmb_camera_info_query.argtypes = (c_char_p, + POINTER(VmbCameraInfo), + c_uint32) + +vmb_camera_open = _vimba_lib.VmbCameraOpen +vmb_camera_open.restype = c_int32 +vmb_camera_open.argtypes = (c_char_p, + c_uint32, + c_void_p) + +vmb_camera_close = _vimba_lib.VmbCameraClose +vmb_camera_close.restype = c_int32 +vmb_camera_close.argtypes = (c_void_p,) + +vmb_features_list = _vimba_lib.VmbFeaturesList +vmb_features_list.restype = c_int32 +vmb_features_list.argtypes = (c_void_p, + POINTER(VmbFeatureInfo), + c_uint32, + POINTER(c_uint32), + c_uint32) + +vmb_feature_info_query = _vimba_lib.VmbFeatureInfoQuery +vmb_feature_info_query.restype = c_int32 +vmb_feature_info_query.argtypes = (c_void_p, + c_char_p, + POINTER(VmbFeatureInfo), + c_uint32) + +# todo VmbFeatureListAffected +# todo VmbFeatureListSelected +# todo VmbFeatureAccessQuery + +vmb_feature_int_get = _vimba_lib.VmbFeatureIntGet +vmb_feature_int_get.restype = c_int32 +vmb_feature_int_get.argtypes = (c_void_p, + c_char_p, + POINTER(c_int64)) + +vmb_feature_int_set = _vimba_lib.VmbFeatureIntSet +vmb_feature_int_set.restype = c_int32 +vmb_feature_int_set.argtypes = (c_void_p, + c_char_p, + c_int64) + +vmb_feature_int_range_query = _vimba_lib.VmbFeatureIntRangeQuery +vmb_feature_int_range_query.restype = c_int32 +vmb_feature_int_range_query.argtypes = (c_void_p, + c_char_p, + POINTER(c_int64), + POINTER(c_int64)) + +# todo VmbFeatureIntIncrementQuery + +vmb_feature_float_get = _vimba_lib.VmbFeatureFloatGet +vmb_feature_float_get.restype = c_int32 +vmb_feature_float_get.argtypes = (c_void_p, + c_char_p, + POINTER(c_double)) + +vmb_feature_float_set = _vimba_lib.VmbFeatureFloatSet +vmb_feature_float_set.restype = c_int32 +vmb_feature_float_set.argtypes = (c_void_p, + c_char_p, + c_double) + +vmb_feature_float_range_query = _vimba_lib.VmbFeatureFloatRangeQuery +vmb_feature_float_range_query.restype = c_int32 +vmb_feature_float_range_query.argtypes = (c_void_p, + c_char_p, + POINTER(c_double), + POINTER(c_double)) + +# todo VmbFeatureFloatIncrementQuery + +vmb_feature_enum_get = _vimba_lib.VmbFeatureEnumGet +vmb_feature_enum_get.restype = c_int32 +vmb_feature_enum_get.argtypes = (c_void_p, + c_char_p, + POINTER(c_char_p)) + +vmb_feature_enum_set = _vimba_lib.VmbFeatureEnumSet +vmb_feature_enum_set.restype = c_int32 +vmb_feature_enum_set.argtypes = (c_void_p, + c_char_p, + c_char_p) + +vmb_feature_enum_range_query = _vimba_lib.VmbFeatureEnumRangeQuery +vmb_feature_enum_range_query.restype = c_int32 +vmb_feature_enum_range_query.argtypes = (c_void_p, + c_char_p, + POINTER(c_char_p), + c_uint32, + POINTER(c_uint32)) + +# todo VmbFeatureEnumIsAvailable +# todo VmbFeatureEnumAsInt +# todo VmbFeatureEnumAsString +# todo VmbFeatureEnumEntryGet + +vmb_feature_string_get = _vimba_lib.VmbFeatureStringGet +vmb_feature_string_get.restype = c_int32 +vmb_feature_string_get.argtypes = (c_void_p, + c_char_p, + c_char_p, + c_uint32, + POINTER(c_uint32)) + +vmb_feature_string_set = _vimba_lib.VmbFeatureStringSet +vmb_feature_string_set.restype = c_int32 +vmb_feature_string_set.argtypes = (c_void_p, + c_char_p, + c_char_p) + +# todo VmbFeatureStringMaxlengthQuery + +vmb_feature_bool_get = _vimba_lib.VmbFeatureBoolGet +vmb_feature_bool_get.restype = c_int32 +vmb_feature_bool_get.argtypes = (c_void_p, + c_char_p, + POINTER(c_bool)) + +vmb_feature_bool_set = _vimba_lib.VmbFeatureBoolSet +vmb_feature_bool_set.restype = c_int32 +vmb_feature_bool_set.argtypes = (c_void_p, + c_char_p, + c_bool) + +vmb_feature_command_run = _vimba_lib.VmbFeatureCommandRun +vmb_feature_command_run.restype = c_int32 +vmb_feature_command_run.argtypes = (c_void_p, + c_char_p) + +vmb_feature_command_is_done = _vimba_lib.VmbFeatureCommandIsDone +vmb_feature_command_is_done.restype = c_int32 +vmb_feature_command_is_done.argtypes = (c_void_p, + c_char_p, + POINTER(c_bool)) + +# todo VmbFeatureRawGet +# todo VmbFeatureRawSet +# todo VmbFeatureRawLengthQuery +# todo VmbFeatureInvalidationRegister +# todo VmbFeatureInvalidationUnregister + +vmb_frame_announce = _vimba_lib.VmbFrameAnnounce +vmb_frame_announce.restype = c_int32 +vmb_frame_announce.argtypes = (c_void_p, + POINTER(VmbFrame), + c_uint32) + +vmb_frame_revoke = _vimba_lib.VmbFrameRevoke +vmb_frame_revoke.restype = c_int32 +vmb_frame_revoke.argtypes = (c_void_p, + POINTER(VmbFrame)) + +vmb_frame_revoke_all = _vimba_lib.VmbFrameRevokeAll +vmb_frame_revoke_all.restype = c_int32 +vmb_frame_revoke_all.argtypes = (c_void_p,) + +vmb_capture_start = _vimba_lib.VmbCaptureStart +vmb_capture_start.restype = c_int32 +vmb_capture_start.argtypes = (c_void_p,) + +vmb_capture_end = _vimba_lib.VmbCaptureEnd +vmb_capture_end.restype = c_int32 +vmb_capture_end.argtypes = (c_void_p,) + +vmb_capture_frame_queue = _vimba_lib.VmbCaptureFrameQueue +vmb_capture_frame_queue.restype = c_int32 +vmb_capture_frame_queue.argtypes = (c_void_p, + POINTER(VmbFrame), + c_void_p) + +vmb_capture_frame_wait = _vimba_lib.VmbCaptureFrameWait +vmb_capture_frame_wait.restype = c_int32 +vmb_capture_frame_wait.argtypes = (c_void_p, + POINTER(VmbFrame), + c_uint32) + +vmb_capture_queue_flush = _vimba_lib.VmbCaptureQueueFlush +vmb_capture_queue_flush.restype = c_int32 +vmb_capture_queue_flush.argtypes = (c_void_p,) + +vmb_interfaces_list = _vimba_lib.VmbInterfacesList +vmb_interfaces_list.restype = c_int32 +vmb_interfaces_list.argtypes = (POINTER(VmbInterfaceInfo), + c_uint32, + POINTER(c_uint32), + c_uint32) + +vmb_interface_open = _vimba_lib.VmbInterfaceOpen +vmb_interface_open.restype = c_int32 +vmb_interface_open.argtypes = (c_char_p, + c_void_p) + +vmb_interface_close = _vimba_lib.VmbInterfaceClose +vmb_interface_close.restype = c_int32 +vmb_interface_close.argtypes = (c_void_p,) + +# todo VmbAncillaryDataOpen +# todo VmbAncillaryDataClose +# todo VmbMemoryRead +# todo VmbMemoryWrite +# todo VmbAncillaryDataOpen + +vmb_registers_read = _vimba_lib.VmbRegistersRead +vmb_registers_read.restype = c_int32 +vmb_registers_read.argtypes = (c_void_p, + c_uint32, + POINTER(c_uint64), + POINTER(c_uint64), + POINTER(c_uint32)) + +vmb_registers_write = _vimba_lib.VmbRegistersWrite +vmb_registers_write.restype = c_int32 +vmb_registers_write.argtypes = (c_void_p, + c_uint32, + POINTER(c_uint64), + POINTER(c_uint64), + POINTER(c_uint32)) + +# todo VmbCameraSettingsSave +# todo VmbCameraSettingsLoad diff --git a/pymba/vimba_dll.py b/pymba/vimba_dll.py deleted file mode 100644 index a62b087..0000000 --- a/pymba/vimba_dll.py +++ /dev/null @@ -1,489 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import - -from sys import platform as sys_plat -import platform -import os -from ctypes import * - -from . import vimba_structure as structs -from .vimba_exception import VimbaException - -if sys_plat == "win32": - - def find_win_dll(arch): - """ Finds the highest versioned windows dll for the specified architecture. """ - bases = [ - r'C:\Program Files\Allied Vision Technologies\AVTVimba_%i.%i\VimbaC\Bin\Win%i\VimbaC.dll', - r'C:\Program Files\Allied Vision\Vimba_%i.%i\VimbaC\Bin\Win%i\VimbaC.dll' - ] - dlls = [] - for base in bases: - for major in range(3): - for minor in range(10): - candidate = base % (major, minor, arch) - if os.path.isfile(candidate): - dlls.append(candidate) - if not dlls: - if 'VIMBA_HOME' in os.environ: - candidate = os.environ ['VIMBA_HOME'] + '\VimbaC\Bin\Win%i\VimbaC.dll' % (arch) - if os.path.isfile(candidate): - dlls.append(candidate) - if not dlls: - raise IOError("VimbaC.dll not found.") - return dlls[-1] - - if '64' in platform.architecture()[0]: - vimbaC_path = find_win_dll(64) - else: - vimbaC_path = find_win_dll(32) - dll_loader = windll -else: - - dll_loader = cdll - - if 'x86_64' in os.uname()[4]: - assert os.environ.get( - "GENICAM_GENTL64_PATH"), "you need your GENICAM_GENTL64_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" - tlPath = [p for p in os.environ.get("GENICAM_GENTL64_PATH").split(":") if p][0] - vimba_dir = "/".join(tlPath.split("/")[1:-3]) - vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/x86_64bit/libVimbaC.so" - elif 'x86_32' in os.uname()[4]: - print("Warning: x86_32 reached!") - assert os.environ.get( - "GENICAM_GENTL32_PATH"), "you need your GENICAM_GENTL32_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" - tlPath = [p for p in os.environ.get("GENICAM_GENTL32_PATH").split(":") if p][0] - vimba_dir = "/".join(tlPath.split("/")[1:-3]) - vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/x86_32bit/libVimbaC.so" - elif 'arm' in os.uname()[4]: - assert os.environ.get( - "GENICAM_GENTL32_PATH"), "you need your GENICAM_GENTL32_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" - tlPath = [p for p in os.environ.get("GENICAM_GENTL32_PATH").split(":") if p][0] - vimba_dir = "/".join(tlPath.split("/")[1:-3]) - vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/arm_32bit/libVimbaC.so" - elif 'aarch64' in os.uname()[4]: - assert os.environ.get( - "GENICAM_GENTL64_PATH"), "you need your GENICAM_GENTL64_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" - tlPath = [p for p in os.environ.get("GENICAM_GENTL64_PATH").split(":") if p][0] - vimba_dir = "/".join(tlPath.split("/")[1:-3]) - vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/arm_64bit/libVimbaC.so" - else: - raise ValueError("Pymba currently doesn't support %s" % os.uname()[4]) - - -# Callback Function Type -if sys_plat == "win32": - CB_FUNCTYPE = WINFUNCTYPE -else: - # Untested! - CB_FUNCTYPE = CFUNCTYPE - - -class VimbaDLL(object): - - """ - ctypes directives to make the wrapper class work cleanly, - talks to VimbaC.dll - """ - # a full list of Vimba API methods - # (only double dashed methods have been implemented so far) - # - # -- VmbVersionQuery() - # - # -- VmbStartup() - # -- VmbShutdown() - # - # -- VmbCamerasList() - # -- VmbCameraInfoQuery() - # -- VmbCameraOpen() - # -- VmbCameraClose() - # - # -- VmbFeaturesList() - # -- VmbFeatureInfoQuery() - # VmbFeatureListAffected() - # VmbFeatureListSelected() - # VmbFeatureAccessQuery() - # - # -- VmbFeatureIntGet() - # -- VmbFeatureIntSet() - # -- VmbFeatureIntRangeQuery() - # VmbFeatureIntIncrementQuery() - # - # -- VmbFeatureFloatGet() - # -- VmbFeatureFloatSet() - # -- VmbFeatureFloatRangeQuery() - # - # -- VmbFeatureEnumGet() - # -- VmbFeatureEnumSet() - # -- VmbFeatureEnumRangeQuery() - # VmbFeatureEnumIsAvailable() - # VmbFeatureEnumAsInt() - # VmbFeatureEnumAsString() - # VmbFeatureEnumEntryGet() - # - # -- VmbFeatureStringGet() - # -- VmbFeatureStringSet() - # VmbFeatureStringMaxlengthQuery() - # - # -- VmbFeatureBoolGet() - # -- VmbFeatureBoolSet() - # - # -- VmbFeatureCommandRun() - # VmbFeatureCommandIsDone() - # - # VmbFeatureRawGet() - # VmbFeatureRawSet() - # VmbFeatureRawLengthQuery() - # - # VmbFeatureInvalidationRegister() - # VmbFeatureInvalidationUnregister() - # - # -- VmbFrameAnnounce() - # -- VmbFrameRevoke() - # -- VmbFrameRevokeAll() - # -- VmbCaptureStart() - # -- VmbCaptureEnd() - # -- VmbCaptureFrameQueue() - # -- VmbCaptureFrameWait() - # -- VmbCaptureQueueFlush() - # - # -- VmbInterfacesList() - # -- VmbInterfaceOpen() - # -- VmbInterfaceClose() - # - # VmbAncillaryDataOpen() - # VmbAncillaryDataClose() - # - # VmbMemoryRead() - # VmbMemoryWrite() - # -- VmbRegistersRead() - # -- VmbRegistersWrite() - - # Vimba C API DLL - _vimbaDLL = dll_loader.LoadLibrary(vimbaC_path) - - # version query - versionQuery = _vimbaDLL.VmbVersionQuery - # returned error code - versionQuery.restype = c_int32 - versionQuery.argtypes = (POINTER(structs.VimbaVersion), # pointer to version structure - c_uint32) # version structure size - - # startup - startup = _vimbaDLL.VmbStartup - # returned error code - startup.restype = c_int32 - - # shutdown - shutdown = _vimbaDLL.VmbShutdown - - # list cameras - camerasList = _vimbaDLL.VmbCamerasList - # returned error code - camerasList.restype = c_int32 - camerasList.argtypes = (POINTER(structs.VimbaCameraInfo), # pointer to camera info structure - # length of list - c_uint32, - # pointer to number of cameras - POINTER(c_uint32), - c_uint32) # camera info structure size - - # camera info query - cameraInfoQuery = _vimbaDLL.VmbCameraInfoQuery - cameraInfoQuery.restype = c_int32 - cameraInfoQuery.argtypes = (c_char_p, # camera unique id - # pointer to camera info structure - POINTER(structs.VimbaCameraInfo), - c_uint32) # size of structure - - # camera open - cameraOpen = _vimbaDLL.VmbCameraOpen - # returned error code - cameraOpen.restype = c_int32 - cameraOpen.argtypes = (c_char_p, # camera unique id - # access mode - c_uint32, - c_void_p) # camera handle, pointer to a pointer - - # camera close - cameraClose = _vimbaDLL.VmbCameraClose - # returned error code - cameraClose.restype = c_int32 - # camera handle - cameraClose.argtypes = (c_void_p,) - - # list features - featuresList = _vimbaDLL.VmbFeaturesList - featuresList.restype = c_int32 - featuresList.argtypes = (c_void_p, # handle, in this case camera handle - # pointer to feature info structure - POINTER(structs.VimbaFeatureInfo), - # list length - c_uint32, - # pointer to num features found - POINTER(c_uint32), - c_uint32) # feature info size - - # feature info query - featureInfoQuery = _vimbaDLL.VmbFeatureInfoQuery - featureInfoQuery.restype = c_int32 - featureInfoQuery.argtypes = (c_void_p, # handle, in this case camera handle - # name of feature - c_char_p, - # pointer to feature info structure - POINTER(structs.VimbaFeatureInfo), - c_uint32) # size of structure - - # get the int value of a feature - featureIntGet = _vimbaDLL.VmbFeatureIntGet - featureIntGet.restype = c_int32 - featureIntGet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - POINTER(c_int64)) # value to get - - # set the int value of a feature - featureIntSet = _vimbaDLL.VmbFeatureIntSet - featureIntSet.restype = c_int32 - featureIntSet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - c_int64) # value to set # get the value of an integer feature - - # query the range of values of the feature - featureIntRangeQuery = _vimbaDLL.VmbFeatureIntRangeQuery - featureIntRangeQuery.restype = c_int32 - featureIntRangeQuery.argtypes = (c_void_p, # handle - # name of the feature - c_char_p, - # min range - POINTER(c_int64), - POINTER(c_int64)) # max range - - # get the float value of a feature - featureFloatGet = _vimbaDLL.VmbFeatureFloatGet - featureFloatGet.restype = c_int32 - featureFloatGet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - POINTER(c_double)) # value to get - - # set the float value of a feature - featureFloatSet = _vimbaDLL.VmbFeatureFloatSet - featureFloatSet.restype = c_int32 - featureFloatSet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - c_double) # value to set - - # query the range of values of the feature - featureFloatRangeQuery = _vimbaDLL.VmbFeatureFloatRangeQuery - featureFloatRangeQuery.restype = c_int32 - featureFloatRangeQuery.argtypes = (c_void_p, # handle - # name of the feature - c_char_p, - # min range - POINTER(c_double), - POINTER(c_double)) # max range - - # get the enum value of a feature - featureEnumGet = _vimbaDLL.VmbFeatureEnumGet - featureEnumGet.restype = c_int32 - featureEnumGet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - POINTER(c_char_p)) # value to get - - # set the enum value of a feature - featureEnumSet = _vimbaDLL.VmbFeatureEnumSet - featureEnumSet.restype = c_int32 - featureEnumSet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - c_char_p) # value to set - - # query the range of values of the feature - featureEnumRangeQuery = _vimbaDLL.VmbFeatureEnumRangeQuery - featureEnumRangeQuery.restype = c_int32 - featureEnumRangeQuery.argtypes = (c_void_p, # handle - # name of the feature - c_char_p, - # pointer to enum names (array) - POINTER(c_char_p), - # array length - c_uint32, - # pointer to num enum names found - POINTER(c_uint32)) - - # get the string value of a feature - featureStringGet = _vimbaDLL.VmbFeatureStringGet - featureStringGet.restype = c_int32 - featureStringGet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - # string buffer to fill - c_char_p, - # size of the input buffer - c_uint32, - POINTER(c_uint32)) # string buffer to fill - - # set the string value of a feature - featureStringSet = _vimbaDLL.VmbFeatureStringSet - featureStringSet.restype = c_int32 - featureStringSet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - c_char_p) # value to set - - # get the boolean value of a feature - featureBoolGet = _vimbaDLL.VmbFeatureBoolGet - featureBoolGet.restype = c_int32 - featureBoolGet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - POINTER(c_bool)) # value to get - - # set the boolean value of a feature - featureBoolSet = _vimbaDLL.VmbFeatureBoolSet - featureBoolSet.restype = c_int32 - featureBoolSet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - c_bool) # value to set - - # run a feature command - featureCommandRun = _vimbaDLL.VmbFeatureCommandRun - featureCommandRun.restype = c_int32 - featureCommandRun.argtypes = (c_void_p, # handle for a module that exposes features - c_char_p) # name of the command feature - - # Check if a feature command is done - featureCommandIsDone = _vimbaDLL.VmbFeatureCommandIsDone - featureCommandIsDone.restype = c_int32 - featureCommandIsDone.argtypes = (c_void_p, # handle - c_char_p, # name of the command feature - POINTER(c_bool)) # pointer to a result bool - - # announce frames to the API that may be queued for frame capturing later - frameAnnounce = _vimbaDLL.VmbFrameAnnounce - frameAnnounce.restype = c_int32 - frameAnnounce.argtypes = (c_void_p, # camera handle - # pointer to frame - POINTER(structs.VimbaFrame), - c_uint32) # size of frame - - # callback for frame queue - frameDoneCallback = CB_FUNCTYPE(c_void_p, # Return Type - c_void_p, # Camera Hanlde - POINTER(structs.VimbaFrame)) # Pointer to frame - - # revoke a frame from the API - frameRevoke = _vimbaDLL.VmbFrameRevoke - frameRevoke.restype = c_int32 - frameRevoke.argtypes = (c_void_p, # camera handle - POINTER(structs.VimbaFrame)) # pointer to frame - - # revoke all frames assigned to a certain camera - frameRevokeAll = _vimbaDLL.VmbFrameRevokeAll - frameRevokeAll.restype = c_int32 - # camera handle - frameRevokeAll.argtypes = (c_void_p,) - - # prepare the API for incoming frames - captureStart = _vimbaDLL.VmbCaptureStart - captureStart.restype = c_int32 - # camera handle - captureStart.argtypes = (c_void_p,) - - # stop the API from being able to receive frames - captureEnd = _vimbaDLL.VmbCaptureEnd - captureEnd.restype = c_int32 - # camera handle - captureEnd.argtypes = (c_void_p,) - - # queue frames that may be filled during frame capturing - captureFrameQueue = _vimbaDLL.VmbCaptureFrameQueue - captureFrameQueue.restype = c_int32 - captureFrameQueue.argtypes = (c_void_p, - POINTER(structs.VimbaFrame), - c_void_p) # callback - - # wait for a queued frame to be filled (or dequeued) - captureFrameWait = _vimbaDLL.VmbCaptureFrameWait - captureFrameWait.restype = c_int32 - captureFrameWait.argtypes = (c_void_p, # camera handle - POINTER(structs.VimbaFrame), - c_uint32) # timeout - - # flush the capture queue - captureQueueFlush = _vimbaDLL.VmbCaptureQueueFlush - captureQueueFlush.restype = c_int32 - # camera handle - captureQueueFlush.argtypes = (c_void_p,) - - # list interfaces - interfacesList = _vimbaDLL.VmbInterfacesList - interfacesList.restype = c_int32 - interfacesList.argtypes = (POINTER(structs.VimbaInterfaceInfo), # pointer to interface info structure - # length of list - c_uint32, - # pointer to number of interfaces - POINTER(c_uint32), - c_uint32) - - # open interface - interfaceOpen = _vimbaDLL.VmbInterfaceOpen - interfaceOpen.restype = c_int32 - interfaceOpen.argtypes = (c_char_p, # unique id - c_void_p) # handle - - # close interface - interfaceClose = _vimbaDLL.VmbInterfaceClose - interfaceClose.restype = c_int32 - interfaceClose.argtypes = (c_void_p,) # handle - - # read from register - registersRead = _vimbaDLL.VmbRegistersRead - registersRead.restype = c_int32 - registersRead.argtypes = (c_void_p, # handle - # read count - c_uint32, - # pointer to address array - POINTER(c_uint64), - # pointer to data array - POINTER(c_uint64), - POINTER(c_uint32)) # pointer to num complete reads - - # write to register - registersWrite = _vimbaDLL.VmbRegistersWrite - registersWrite.restype = c_int32 - registersWrite.argtypes = (c_void_p, # handle - # write count - c_uint32, - # pointer to address array - POINTER(c_uint64), - # pointer to data array - POINTER(c_uint64), - POINTER(c_uint32)) # pointer to num complete write - - -class VimbaC_MemoryBlock(object): - - """ - Just a memory block object for dealing - neatly with C memory allocations. - """ - - @property - def block(self): - return c_void_p(addressof(self._block)) - - def __init__(self, blockSize): - self._block = create_string_buffer(blockSize) - - # this seems to be None if too much memory is requested - if self._block is None: - raise VimbaException(-51) - - def __del__(self): - del self._block diff --git a/pymba/vimba_structure.py b/pymba/vimba_structure.py deleted file mode 100644 index 73c4e96..0000000 --- a/pymba/vimba_structure.py +++ /dev/null @@ -1,106 +0,0 @@ -# -*- coding: utf-8 -*- -from ctypes import * - - -class VimbaVersion(Structure): - _fields_ = [('major', c_uint32), - ('minor', c_uint32), - ('patch', c_uint32)] - - -class VimbaInterfaceInfo(Structure): - _fields_ = [('interfaceIdString', c_char_p), # Unique identifier for each interface - # Interface type, see VmbInterfaceType - ('interfaceType', c_uint32), - # Interface name, given by the transport layer - ('interfaceName', c_char_p), - ('serialString', c_char_p), # Serial number - ('permittedAccess', c_uint32)] # Used access mode, see VmbAccessModeType - - def getFieldNames(self): - """ - Get field names. - """ - return [field[0] for field in self._fields_] - - -class VimbaCameraInfo(Structure): - _fields_ = [('cameraIdString', c_char_p), # Unique identifier for each camera - ('cameraName', c_char_p), # Name of the camera - ('modelName', c_char_p), # Model name - ('serialString', c_char_p), # Serial number - # Used access mode, see VmbAccessModeType - ('permittedAccess', c_uint32), - ('interfaceIdString', c_char_p)] # Unique value for each interface or bus - - def getFieldNames(self): - """ - Get field names. - """ - return [field[0] for field in self._fields_] - - -class VimbaFeatureInfo(Structure): - - _fields_ = [('name', c_char_p), - ('featureDataType', c_uint32), - ('featureFlags', c_uint32), - ('category', c_char_p), - ('displayName', c_char_p), - ('pollingTime', c_uint32), - ('unit', c_char_p), - ('representation', c_char_p), - ('visibility', c_uint32), - ('tooltip', c_char_p), - ('description', c_char_p), - ('sfncNamespace', c_char_p), - ('isStreamable', c_bool), - ('hasAffectedFeatures', c_bool), - ('hasSelectedFeatures', c_bool)] - - def getFieldNames(self): - """ - Get field names. - """ - return [field[0] for field in self._fields_] - - -class VimbaFrame(Structure): - - # IN - _fields_ = [('buffer', c_void_p), # Comprises image and ancillary data - ('bufferSize', c_uint32), # Size of the data buffer - - # User context filled during queuing - ('context', c_void_p * 4), - - # OUT - # Resulting status of the receive operation - ('receiveStatus', c_int32), - # Resulting flags of the receive operation - ('receiveFlags', c_uint32), - - # Size of the image data inside the data buffer - ('imageSize', c_uint32), - # Size of the ancillary data inside the data buffer - ('ancillarySize', c_uint32), - - # Pixel format of the image - ('pixelFormat', c_uint32), - - ('width', c_uint32), # Width of an image - ('height', c_uint32), # Height of an image - # Horizontal offset of an image - ('offsetX', c_uint32), - # Vertical offset of an image - ('offsetY', c_uint32), - - # Unique ID of this frame in this stream - ('frameID', c_uint64), - ('timestamp', c_uint64)] # Timestamp of the data transfer - - def getFieldNames(self): - """ - Get field names. - """ - return [field[0] for field in self._fields_] -- cgit v1.2.3 From fb2c6933efbae38e3387f2e07b1f7db4bdf58b23 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 14:14:46 +1100 Subject: clean up exception class --- pymba/vimba_exception.py | 125 +++++++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 53 deletions(-) diff --git a/pymba/vimba_exception.py b/pymba/vimba_exception.py index 6269543..37666ca 100644 --- a/pymba/vimba_exception.py +++ b/pymba/vimba_exception.py @@ -1,61 +1,80 @@ -# -*- coding: utf-8 -*- +ERROR_CODES = ( + # 0 + ERR_NO_ERROR, + # -1 to -19 + ERR_UNEXPECTED_FAULT, + ERR_STARTUP_NOT_CALLED, + ERR_INSTANCE_NOT_FOUND, + ERR_HANDLE_INVALID, + ERR_DEVICE_NOT_OPENED, + ERR_OPERATION_INVALID_FOR_ACCESS_MODE, + ERR_PARAMETER_INVALID, + ERR_STRUCT_SIZE_INVALID, + ERR_DATA_TOO_LARGE, + ERR_FEATURE_TYPE_WRONG, + ERR_VALUE_INVALID, + ERR_TIMEOUT, + ERR_OTHER_ERROR, + ERR_RESOURCE_NOT_AVAILABLE, + ERR_CALL_INVALID, + ERR_TRANSPORT_LAYER_NOT_FOUND, + ERR_FEATURE_NOT_IMPLEMENTED, + ERR_FEATURE_NOT_SUPPORTED, + ERR_PARTIAL_REGISTER_ACCESS, -class VimbaException(Exception): + # -50 to -56 + ERR_CAMERA_NOT_FOUND, + ERR_FRAME_BUFFER_MEMORY, + ERR_INVALID_INPUT, + ERR_FEATURE_NOT_FOUND, + ERR_INTERFACE_NOT_FOUND, + ERR_NOT_IMPLEMENTED_IN_PYMBA, + ERR_UNDEFINED_ERROR_CODE, +) = tuple(range(0, -20, -1)) + tuple(range(-50, -57, -1)) + +ERRORS = { + # Vimba C API specific errors + ERR_NO_ERROR: 'No error.', + ERR_UNEXPECTED_FAULT: 'Unexpected fault in VimbaC or driver.', + ERR_STARTUP_NOT_CALLED: 'VmbStartup() was not called before the current command.', + ERR_INSTANCE_NOT_FOUND: 'The designated instance (camera, feature etc.) cannot be found.', + ERR_HANDLE_INVALID: 'The given handle is not valid, ensure device open.', + ERR_DEVICE_NOT_OPENED: 'Device was not opened for usage.', + ERR_OPERATION_INVALID_FOR_ACCESS_MODE: 'Operation is invalid with the current access mode.', + ERR_PARAMETER_INVALID: 'One of the parameters was invalid (usually an illegal pointer).', + ERR_STRUCT_SIZE_INVALID: 'The given struct size is not valid for this version of the API.', + ERR_DATA_TOO_LARGE: 'More data was returned in a string/list than space was provided.', + ERR_FEATURE_TYPE_WRONG: 'The feature type for this access function was wrong.', + ERR_VALUE_INVALID: 'The value was not valid; either out of bounds or not an increment of the minimum.', + ERR_TIMEOUT: 'Timeout during wait.', + ERR_OTHER_ERROR: 'Other error.', + ERR_RESOURCE_NOT_AVAILABLE: 'Resources not available (e.g. memory).', + ERR_CALL_INVALID: 'Call is invalid in the current context (e.g. callback).', + ERR_TRANSPORT_LAYER_NOT_FOUND: 'No transport layers were found.', + ERR_FEATURE_NOT_IMPLEMENTED: 'API feature is not implemented.', + ERR_FEATURE_NOT_SUPPORTED: 'API feature is not supported.', + ERR_PARTIAL_REGISTER_ACCESS: 'A multiple registers read or write was partially completed.', - """ - An exception for the AVT Vimba API. It contains a message - property which is a string indicating what went wrong. + # Custom errors + ERR_CAMERA_NOT_FOUND: 'Could not find the specified camera.', + ERR_FRAME_BUFFER_MEMORY: 'Not enough memory to assign frame buffer.', + ERR_INVALID_INPUT: 'Invalid input.', + ERR_FEATURE_NOT_FOUND: 'Could not find the specified feature.', + ERR_INTERFACE_NOT_FOUND: 'Could not find the specified interface.', + ERR_NOT_IMPLEMENTED_IN_PYMBA: 'This function is not yet implemented in Pymba', + ERR_UNDEFINED_ERROR_CODE: 'Undefined error code', +} - :param errorCode: Error code to be used to look up error message. - """ +class VimbaException(Exception): @property def message(self): - return self._errorCodes[self.errorCode] + return ERRORS[self.error_code] - @property - def errorCode(self): - return self._errorCode - - _errorCodes = { # Vimba C API specific errors - 0: 'No error.', - -1: 'Unexpected fault in VimbaC or driver.', - -2: 'VmbStartup() was not called before the current command.', - -3: 'The designated instance (camera, feature etc.) cannot be found.', - -4: 'The given handle is not valid, ensure device open.', - -5: 'Device was not opened for usage.', - -6: 'Operation is invalid with the current access mode.', - -7: 'One of the parameters was invalid (usually an illegal pointer).', - -8: 'The given struct size is not valid for this version of the API.', - -9: 'More data was returned in a string/list than space was provided.', - -10: 'The feature type for this access function was wrong.', - -11: 'The value was not valid; either out of bounds or not an increment of the minimum.', - -12: 'Timeout during wait.', - -13: 'Other error.', - -14: 'Resources not available (e.g. memory).', - -15: 'Call is invalid in the current context (e.g. callback).', - -16: 'No transport layers were found.', - -17: 'API feature is not implemented.', - -18: 'API feature is not supported.', - -19: 'A multiple registers read or write was partially completed.', - - # Custom errors - -50: 'Could not find the specified camera.', - -51: 'Not enough memory to assign frame buffer.', - -52: 'Invalid input.', - -53: 'Could not find the specified feature.', - -54: 'Could not find the specified interface.', - - # Miscellaneous errors - -1000: 'Oops, unknown internal error code!', - -1001: 'Oops, this VimbaFeature function is not yet implemented in pymba!'} - - def __init__(self, errorCode): - # if error code does not match expected codes then assign invalid code - if errorCode in self._errorCodes: - self._errorCode = errorCode - else: - self._errorCode = -1000 - - super(VimbaException, self).__init__(self.message) + def __init__(self, error_code: int): + if error_code not in ERROR_CODES: + error_code = ERR_UNDEFINED_ERROR_CODE + self.error_code = error_code + + super().__init__(self.message) -- cgit v1.2.3 From 94e2944701ac966431505cb75235b30e501fa0b6 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 14:35:51 +1100 Subject: error codes as class consts --- pymba/vimba_exception.py | 134 +++++++++++++++++++++++------------------------ 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/pymba/vimba_exception.py b/pymba/vimba_exception.py index 37666ca..4ce9e93 100644 --- a/pymba/vimba_exception.py +++ b/pymba/vimba_exception.py @@ -1,80 +1,80 @@ -ERROR_CODES = ( - # 0 - ERR_NO_ERROR, - # -1 to -19 - ERR_UNEXPECTED_FAULT, - ERR_STARTUP_NOT_CALLED, - ERR_INSTANCE_NOT_FOUND, - ERR_HANDLE_INVALID, - ERR_DEVICE_NOT_OPENED, - ERR_OPERATION_INVALID_FOR_ACCESS_MODE, - ERR_PARAMETER_INVALID, - ERR_STRUCT_SIZE_INVALID, - ERR_DATA_TOO_LARGE, - ERR_FEATURE_TYPE_WRONG, - ERR_VALUE_INVALID, - ERR_TIMEOUT, - ERR_OTHER_ERROR, - ERR_RESOURCE_NOT_AVAILABLE, - ERR_CALL_INVALID, - ERR_TRANSPORT_LAYER_NOT_FOUND, - ERR_FEATURE_NOT_IMPLEMENTED, - ERR_FEATURE_NOT_SUPPORTED, - ERR_PARTIAL_REGISTER_ACCESS, +class VimbaException(Exception): + ERROR_CODES = ( + # 0 + ERR_NO_ERROR, - # -50 to -56 - ERR_CAMERA_NOT_FOUND, - ERR_FRAME_BUFFER_MEMORY, - ERR_INVALID_INPUT, - ERR_FEATURE_NOT_FOUND, - ERR_INTERFACE_NOT_FOUND, - ERR_NOT_IMPLEMENTED_IN_PYMBA, - ERR_UNDEFINED_ERROR_CODE, -) = tuple(range(0, -20, -1)) + tuple(range(-50, -57, -1)) + # -1 to -19 + ERR_UNEXPECTED_FAULT, + ERR_STARTUP_NOT_CALLED, + ERR_INSTANCE_NOT_FOUND, + ERR_HANDLE_INVALID, + ERR_DEVICE_NOT_OPENED, + ERR_OPERATION_INVALID_FOR_ACCESS_MODE, + ERR_PARAMETER_INVALID, + ERR_STRUCT_SIZE_INVALID, + ERR_DATA_TOO_LARGE, + ERR_FEATURE_TYPE_WRONG, + ERR_VALUE_INVALID, + ERR_TIMEOUT, + ERR_OTHER_ERROR, + ERR_RESOURCE_NOT_AVAILABLE, + ERR_CALL_INVALID, + ERR_TRANSPORT_LAYER_NOT_FOUND, + ERR_FEATURE_NOT_IMPLEMENTED, + ERR_FEATURE_NOT_SUPPORTED, + ERR_PARTIAL_REGISTER_ACCESS, -ERRORS = { - # Vimba C API specific errors - ERR_NO_ERROR: 'No error.', - ERR_UNEXPECTED_FAULT: 'Unexpected fault in VimbaC or driver.', - ERR_STARTUP_NOT_CALLED: 'VmbStartup() was not called before the current command.', - ERR_INSTANCE_NOT_FOUND: 'The designated instance (camera, feature etc.) cannot be found.', - ERR_HANDLE_INVALID: 'The given handle is not valid, ensure device open.', - ERR_DEVICE_NOT_OPENED: 'Device was not opened for usage.', - ERR_OPERATION_INVALID_FOR_ACCESS_MODE: 'Operation is invalid with the current access mode.', - ERR_PARAMETER_INVALID: 'One of the parameters was invalid (usually an illegal pointer).', - ERR_STRUCT_SIZE_INVALID: 'The given struct size is not valid for this version of the API.', - ERR_DATA_TOO_LARGE: 'More data was returned in a string/list than space was provided.', - ERR_FEATURE_TYPE_WRONG: 'The feature type for this access function was wrong.', - ERR_VALUE_INVALID: 'The value was not valid; either out of bounds or not an increment of the minimum.', - ERR_TIMEOUT: 'Timeout during wait.', - ERR_OTHER_ERROR: 'Other error.', - ERR_RESOURCE_NOT_AVAILABLE: 'Resources not available (e.g. memory).', - ERR_CALL_INVALID: 'Call is invalid in the current context (e.g. callback).', - ERR_TRANSPORT_LAYER_NOT_FOUND: 'No transport layers were found.', - ERR_FEATURE_NOT_IMPLEMENTED: 'API feature is not implemented.', - ERR_FEATURE_NOT_SUPPORTED: 'API feature is not supported.', - ERR_PARTIAL_REGISTER_ACCESS: 'A multiple registers read or write was partially completed.', + # -50 to -56 + ERR_CAMERA_NOT_FOUND, + ERR_FRAME_BUFFER_MEMORY, + ERR_INVALID_INPUT, + ERR_FEATURE_NOT_FOUND, + ERR_INTERFACE_NOT_FOUND, + ERR_NOT_IMPLEMENTED_IN_PYMBA, + ERR_UNDEFINED_ERROR_CODE, + ) = tuple(range(0, -20, -1)) + tuple(range(-50, -57, -1)) - # Custom errors - ERR_CAMERA_NOT_FOUND: 'Could not find the specified camera.', - ERR_FRAME_BUFFER_MEMORY: 'Not enough memory to assign frame buffer.', - ERR_INVALID_INPUT: 'Invalid input.', - ERR_FEATURE_NOT_FOUND: 'Could not find the specified feature.', - ERR_INTERFACE_NOT_FOUND: 'Could not find the specified interface.', - ERR_NOT_IMPLEMENTED_IN_PYMBA: 'This function is not yet implemented in Pymba', - ERR_UNDEFINED_ERROR_CODE: 'Undefined error code', -} + ERRORS = { + # Vimba C API specific errors + ERR_NO_ERROR: 'No error.', + ERR_UNEXPECTED_FAULT: 'Unexpected fault in VimbaC or driver.', + ERR_STARTUP_NOT_CALLED: 'VmbStartup() was not called before the current command.', + ERR_INSTANCE_NOT_FOUND: 'The designated instance (camera, feature etc.) cannot be found.', + ERR_HANDLE_INVALID: 'The given handle is not valid, ensure device open.', + ERR_DEVICE_NOT_OPENED: 'Device was not opened for usage.', + ERR_OPERATION_INVALID_FOR_ACCESS_MODE: 'Operation is invalid with the current access mode.', + ERR_PARAMETER_INVALID: 'One of the parameters was invalid (usually an illegal pointer).', + ERR_STRUCT_SIZE_INVALID: 'The given struct size is not valid for this version of the API.', + ERR_DATA_TOO_LARGE: 'More data was returned in a string/list than space was provided.', + ERR_FEATURE_TYPE_WRONG: 'The feature type for this access function was wrong.', + ERR_VALUE_INVALID: 'The value was not valid; either out of bounds or not an increment of the minimum.', + ERR_TIMEOUT: 'Timeout during wait.', + ERR_OTHER_ERROR: 'Other error.', + ERR_RESOURCE_NOT_AVAILABLE: 'Resources not available (e.g. memory).', + ERR_CALL_INVALID: 'Call is invalid in the current context (e.g. callback).', + ERR_TRANSPORT_LAYER_NOT_FOUND: 'No transport layers were found.', + ERR_FEATURE_NOT_IMPLEMENTED: 'API feature is not implemented.', + ERR_FEATURE_NOT_SUPPORTED: 'API feature is not supported.', + ERR_PARTIAL_REGISTER_ACCESS: 'A multiple registers read or write was partially completed.', + # Custom errors + ERR_CAMERA_NOT_FOUND: 'Could not find the specified camera.', + ERR_FRAME_BUFFER_MEMORY: 'Not enough memory to assign frame buffer.', + ERR_INVALID_INPUT: 'Invalid input.', + ERR_FEATURE_NOT_FOUND: 'Could not find the specified feature.', + ERR_INTERFACE_NOT_FOUND: 'Could not find the specified interface.', + ERR_NOT_IMPLEMENTED_IN_PYMBA: 'This function is not yet implemented in Pymba', + ERR_UNDEFINED_ERROR_CODE: 'Undefined error code', + } -class VimbaException(Exception): @property def message(self): - return ERRORS[self.error_code] + return self.ERRORS[self.error_code] def __init__(self, error_code: int): - if error_code not in ERROR_CODES: - error_code = ERR_UNDEFINED_ERROR_CODE + if error_code not in self.ERROR_CODES: + error_code = self.ERR_UNDEFINED_ERROR_CODE self.error_code = error_code super().__init__(self.message) -- cgit v1.2.3 From 37464638be0c50de7c908f121d6309207435ad48 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 15:36:28 +1100 Subject: error moved to class --- pymba/vimba_c.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pymba/vimba_c.py b/pymba/vimba_c.py index 5ddc5c0..ef547ae 100644 --- a/pymba/vimba_c.py +++ b/pymba/vimba_c.py @@ -89,7 +89,7 @@ class MemoryBlock: # this seems to be None if too much memory is requested if self._block is None: - raise VimbaException(-51) + raise VimbaException(VimbaException.ERR_FRAME_BUFFER_MEMORY) def __del__(self): del self._block -- cgit v1.2.3 From a96013435f3239e2780ee01173666dc004103d12 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 16:03:20 +1100 Subject: clean up feature class --- pymba/vimba_feature.py | 470 +++++++++++++++++++------------------------------ 1 file changed, 177 insertions(+), 293 deletions(-) diff --git a/pymba/vimba_feature.py b/pymba/vimba_feature.py index 3e838f0..d500d3d 100644 --- a/pymba/vimba_feature.py +++ b/pymba/vimba_feature.py @@ -1,19 +1,27 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from . import vimba_structure as structs -from .vimba_exception import VimbaException -from .vimba_dll import VimbaDLL -from ctypes import * - -# class may extend a generic Vimba entity class one day... +from ctypes import byref, sizeof, c_uint32, c_double, c_char_p, c_bool, c_int64, create_string_buffer +from typing import Tuple, List +from .vimba_exception import VimbaException +from . import vimba_c -class VimbaFeature(object): +class VimbaFeature: """ A feature of a Vimba object. """ + ( + _FEATURE_DATA_UNKNOWN, + _FEATURE_DATA_INT, + _FEATURE_DATA_FLOAT, + _FEATURE_DATA_ENUM, + _FEATURE_DATA_STRING, + _FEATURE_DATA_BOOL, + _FEATURE_DATA_COMMAND, + _FEATURE_DATA_RAW, + _FEATURE_DATA_NONE, + ) = range(9) + @property def name(self): return self._name.decode() @@ -25,317 +33,193 @@ class VimbaFeature(object): # lookup relevant function for feature type and pass to that function @property def value(self): - return self._getSetTypeFuncs[self._info.featureDataType][0]() + return self._feature_data_value_funcs[self._info.featureDataType][0]() @value.setter def value(self, val): - self._getSetTypeFuncs[self._info.featureDataType][1](val) + self._feature_data_value_funcs[self._info.featureDataType][1](val) @property def range(self): - return self._rangeQueryTypeFuncs[self._info.featureDataType]() + return self._feature_data_range_funcs[self._info.featureDataType]() def __init__(self, name, handle): - - # set name and handle self._name = name.encode() self._handle = handle - # set own info - self._info = self._getInfo() - # type functions dict for looking up correct get/set function to use - self._getSetTypeFuncs = {0: (self._notYetImplemented, self._notYetImplemented), # todo - 1: (self._getIntFeature, self._setIntFeature), - 2: (self._getFloatFeature, self._setFloatFeature), - 3: (self._getEnumFeature, self._setEnumFeature), - 4: (self._getStringFeature, self._setStringFeature), - 5: (self._getBoolFeature, self._setBoolFeature), - # todo - 6: (self._notYetImplemented, self._notYetImplemented), - # todo - 7: (self._notYetImplemented, self._notYetImplemented), - 8: (self._notYetImplemented, self._notYetImplemented)} # todo + self._feature_data_value_funcs = { + self._FEATURE_DATA_UNKNOWN: None, + self._FEATURE_DATA_INT: (self._get_int, self._set_int), + self._FEATURE_DATA_FLOAT: (self._get_float, self._set_float), + self._FEATURE_DATA_ENUM: (self._get_enum, self._set_enum), + self._FEATURE_DATA_STRING: (self._get_string, self._set_string), + self._FEATURE_DATA_BOOL: (self._get_bool, self._set_bool), + self._FEATURE_DATA_COMMAND: None, + self._FEATURE_DATA_RAW: None, + self._FEATURE_DATA_NONE: None, + } # type functions dict for looking up correct range function to use - self._rangeQueryTypeFuncs = {0: self._unknownRange, - 1: self._rangeQueryIntFeature, - 2: self._rangeQueryFloatFeature, - 3: self._rangeQueryEnumFeature, - 4: self._unknownRange, - 5: self._unknownRange, - 6: self._unknownRange, - 7: self._unknownRange, - 8: self._unknownRange} - - def getInfo(self): - """ - Get info of the feature. - - :returns: VimbaFeatureInfo object -- feature information.. - """ - return self._info - - def _getInfo(self): - """ - Get info of the feature. - - :returns: VimbaFeatureInfo object -- feature information.. - """ - # args for Vimba call - featureInfo = structs.VimbaFeatureInfo() - - # Vimba DLL will return an error code - errorCode = VimbaDLL.featureInfoQuery(self._handle, - self._name, - byref(featureInfo), - sizeof(featureInfo)) - if errorCode != 0: - raise VimbaException(errorCode) - - return featureInfo - - def _notYetImplemented(self, val=None): - """ - Raises exception if feature value type is not yet defined. - """ - raise VimbaException(-1001) - - def _getIntFeature(self): - """ - Get the value of an integer feature. - - :returns: int -- value of the specified feature. - """ - - # create args - valueToGet = c_int64() - - errorCode = VimbaDLL.featureIntGet(self._handle, - self._name, - byref(valueToGet)) - if errorCode != 0: - raise VimbaException(errorCode) - - return valueToGet.value - - def _setIntFeature(self, valueToSet): - """ - Set the value of an integer feature. - - :param valueToSet: the int value to set for the feature. - """ - - errorCode = VimbaDLL.featureIntSet(self._handle, - self._name, - valueToSet) - if errorCode != 0: - raise VimbaException(errorCode) - - def _getFloatFeature(self): - """ - Get the value of a float feature. - - :returns: float -- value of the specified feature. - """ - - # create args - valueToGet = c_double() - - errorCode = VimbaDLL.featureFloatGet(self._handle, - self._name, - byref(valueToGet)) - if errorCode != 0: - raise VimbaException(errorCode) - - return valueToGet.value - - def _setFloatFeature(self, valueToSet): - """ - Set the value of a float feature. - - :param valueToSet: the float value to set for the feature. - """ - - errorCode = VimbaDLL.featureFloatSet(self._handle, - self._name, - valueToSet) - if errorCode != 0: - raise VimbaException(errorCode) - - def _getEnumFeature(self): - """ - Get the value of an enum feature. - - :returns: enum -- value of the specified feature. - """ - - # create args - valueToGet = c_char_p() - - errorCode = VimbaDLL.featureEnumGet(self._handle, + self._feature_data_range_funcs = { + self._FEATURE_DATA_UNKNOWN: None, + self._FEATURE_DATA_INT: self._range_query_int, + self._FEATURE_DATA_FLOAT: self._range_query_float, + self._FEATURE_DATA_ENUM: self._range_query_enum, + self._FEATURE_DATA_STRING: None, + self._FEATURE_DATA_BOOL: None, + self._FEATURE_DATA_COMMAND: None, + self._FEATURE_DATA_RAW: None, + self._FEATURE_DATA_NONE: None, + } + + # get info once + self._info = self._get_info() + + def _get_info(self) -> vimba_c.VmbFeatureInfo: + feature_info = vimba_c.VmbFeatureInfo() + error = vimba_c.vmb_feature_info_query(self._handle, + self._name, + byref(feature_info), + sizeof(feature_info)) + if error: + raise VimbaException(error) + + return feature_info + + def _get_int(self) -> int: + value = c_int64() + error = vimba_c.vmb_feature_int_get(self._handle, self._name, - byref(valueToGet)) - if errorCode != 0: - raise VimbaException(errorCode) - - return valueToGet.value.decode() + byref(value)) + if error: + raise VimbaException(error) - def _setEnumFeature(self, valueToSet): - """ - Set the value of an enum feature. + return value.value - :param valueToSet: the enum value to set for the feature. - """ - - errorCode = VimbaDLL.featureEnumSet(self._handle, + def _set_int(self, value: int) -> None: + error = vimba_c.vmb_feature_int_set(self._handle, self._name, - valueToSet.encode()) - if errorCode != 0: - raise VimbaException(errorCode) - - def _getStringFeature(self): - """ - Get the value of a string feature. - - :returns: string -- value of the specified feature. - """ + value) + if error: + raise VimbaException(error) - # create args - bufferSize = 256 - valueToGet = create_string_buffer('\000' * bufferSize) - sizeFilled = c_uint32() - - errorCode = VimbaDLL.featureStringGet(self._handle, + def _get_float(self) -> float: + value = c_double() + error = vimba_c.vmb_feature_float_get(self._handle, self._name, - valueToGet, - bufferSize, - byref(sizeFilled)) - if errorCode != 0: - raise VimbaException(errorCode) - return valueToGet.value.decode() - - def _setStringFeature(self, valueToSet): - """ - Set the value of a string feature. + byref(value)) + if error: + raise VimbaException(error) - :param valueToSet: the string value to set for the feature. - """ + return value.value - errorCode = VimbaDLL.featureStringSet(self._handle, + def _set_float(self, value: float) -> None: + error = vimba_c.vmb_feature_float_set(self._handle, self._name, - valueToSet.encode()) - if errorCode != 0: - raise VimbaException(errorCode) - - def _getBoolFeature(self): - """ - Get the value of a bool feature. - - :returns: bool -- value of the specified feature. - """ - - # create args - valueToGet = c_bool() - - errorCode = VimbaDLL.featureBoolGet(self._handle, - self._name, - byref(valueToGet)) - if errorCode != 0: - raise VimbaException(errorCode) + value) + if error: + raise VimbaException(error) - return valueToGet.value - - def _setBoolFeature(self, valueToSet): - """ - Set the value of a bool feature. - - :param valueToSet: the bool value to set for the feature. - """ - - errorCode = VimbaDLL.featureBoolSet(self._handle, - self._name, - valueToSet) - if errorCode != 0: - raise VimbaException(errorCode) - - def _unknownRange(self): - """ - Returns empty for ranges that have not been implemented. - """ - return '' - - def _rangeQueryIntFeature(self): - """ - Get the range of an int feature. - - :returns: tuple -- min and max range. - """ - - # create args - minToGet = c_int64() - maxToGet = c_int64() - - errorCode = VimbaDLL.featureIntRangeQuery(self._handle, - self._name, - byref(minToGet), - byref(maxToGet)) - if errorCode != 0: - raise VimbaException(errorCode) - - return int(str(minToGet.value)), int(str(maxToGet.value)) + def _get_enum(self) -> str: + value = c_char_p() + error = vimba_c.vmb_feature_enum_get(self._handle, + self._name, + byref(value)) + if error: + raise VimbaException(error) - def _rangeQueryFloatFeature(self): - """ - Get the range of a float feature. + return value.value.decode() - :returns: tuple -- min and max range. - """ + def _set_enum(self, value: str): + error = vimba_c.vmb_feature_enum_set(self._handle, + self._name, + value.encode()) + if error: + raise VimbaException(error) + + def _get_string(self) -> str: + buffer_size = 256 + value = create_string_buffer('\x00' * buffer_size) + size_filled = c_uint32() + + error = vimba_c.vmb_feature_string_get(self._handle, + self._name, + value, + buffer_size, + byref(size_filled)) + if error: + raise VimbaException(error) + return value.value.decode() + + def _set_string(self, value: str) -> None: + error = vimba_c.vmb_feature_string_set(self._handle, + self._name, + value.encode()) + if error: + raise VimbaException(error) + + def _get_bool(self) -> bool: + value = c_bool() + error = vimba_c.vmb_feature_bool_get(self._handle, + self._name, + byref(value)) + if error: + raise VimbaException(error) - # create args - minToGet = c_double() - maxToGet = c_double() + return value.value - errorCode = VimbaDLL.featureFloatRangeQuery(self._handle, + def _set_bool(self, value: bool): + error = vimba_c.vmb_feature_bool_set(self._handle, + self._name, + value) + if error: + raise VimbaException(error) + + def _range_query_int(self) -> Tuple[int, int]: + range_min = c_int64() + range_max = c_int64() + error = vimba_c.vmb_feature_int_range_query(self._handle, self._name, - byref(minToGet), - byref(maxToGet)) - if errorCode != 0: - raise VimbaException(errorCode) - - return (minToGet.value, maxToGet.value) - - def _rangeQueryEnumFeature(self): - """ - Get the range of an enum feature. - :returns: list -- enum names for the given feature. - """ - + byref(range_min), + byref(range_max)) + if error: + raise VimbaException(error) + + return int(range_min.value), int(range_max.value) + + def _range_query_float(self) -> Tuple[float, float]: + range_min = c_double() + range_max = c_double() + error = vimba_c.vmb_feature_float_range_query(self._handle, + self._name, + byref(range_min), + byref(range_max)) + if error: + raise VimbaException(error) + + return range_min.value, range_max.value + + def _range_query_enum(self) -> List[str]: # call once to get number of available enum names - # Vimba DLL will return an error code - numFound = c_uint32(-1) - errorCode = VimbaDLL.featureEnumRangeQuery(self._handle, - self._name, - None, - 0, - byref(numFound)) - if errorCode != 0: - raise VimbaException(errorCode) - - # number of names specified by Vimba - numEnumNames = numFound.value - - # args - enumNamesArray = (c_char_p * numEnumNames)() - - # call again to get the enum names - # Vimba DLL will return an error code - errorCode = VimbaDLL.featureEnumRangeQuery(self._handle, - self._name, - enumNamesArray, - numEnumNames, - byref(numFound)) - if errorCode != 0: - raise VimbaException(errorCode) - - return list(enumName.decode() for enumName in enumNamesArray) + num_found = c_uint32(-1) + error = vimba_c.vmb_feature_enum_range_query(self._handle, + self._name, + None, + 0, + byref(num_found)) + if error: + raise VimbaException(error) + + # call again to get the actual enum names + num_enum_names = num_found.value + enum_names = (c_char_p * num_enum_names)() + error = vimba_c.vmb_feature_enum_range_query(self._handle, + self._name, + enum_names, + num_enum_names, + byref(num_found)) + if error: + raise VimbaException(error) + + return list(enum_name.decode() for enum_name in enum_names) -- cgit v1.2.3 From 81c5d5eea267cd35517bae1ed50d4bdeb8b3a62c Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 16:13:37 +1100 Subject: clean up interface class --- pymba/vimba_interface.py | 44 +++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/pymba/vimba_interface.py b/pymba/vimba_interface.py index df5acdc..b2b8890 100644 --- a/pymba/vimba_interface.py +++ b/pymba/vimba_interface.py @@ -1,47 +1,37 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from . import vimba_structure as structs +from ctypes import byref + from .vimba_object import VimbaObject from .vimba_exception import VimbaException -from .vimba_dll import VimbaDLL -from ctypes import * - -# interface features are automatically readable as object attributes. +from . import vimba_c class VimbaInterface(VimbaObject): - """ A Vimba interface object. This class provides the minimal access to Vimba functions required to control the interface. """ - @property - def interfaceIdString(self): - return self._interfaceIdString + def __init__(self, id_string: str): + self._id_string = id_string + super().__init__() - # own handle is inherited as self._handle - def __init__(self, interfaceIdString): - - # call super constructor - super(VimbaInterface, self).__init__() - - # set ID - self._interfaceIdString = interfaceIdString + @property + def id_string(self): + return self._id_string - def openInterface(self): + def open(self): """ Open the interface. """ - errorCode = VimbaDLL.interfaceOpen(self._interfaceIdString, + error = vimba_c.vmb_interface_open(self._id_string, byref(self._handle)) - if errorCode != 0: - raise VimbaException(errorCode) + if error: + raise VimbaException(error) - def closeInterface(self): + def close(self): """ Close the interface. """ - errorCode = VimbaDLL.interfaceClose(self._handle) - if errorCode != 0: - raise VimbaException(errorCode) + error = vimba_c.vmb_interface_close(self._handle) + if error: + raise VimbaException(error) -- cgit v1.2.3 From ca19dc08cd13328327adc64af193553d13080878 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 16:20:54 +1100 Subject: consistent naming with vimba structs --- pymba/vimba_feature.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pymba/vimba_feature.py b/pymba/vimba_feature.py index d500d3d..6e68bea 100644 --- a/pymba/vimba_feature.py +++ b/pymba/vimba_feature.py @@ -77,15 +77,15 @@ class VimbaFeature: self._info = self._get_info() def _get_info(self) -> vimba_c.VmbFeatureInfo: - feature_info = vimba_c.VmbFeatureInfo() + vmb_feature_info = vimba_c.VmbFeatureInfo() error = vimba_c.vmb_feature_info_query(self._handle, self._name, - byref(feature_info), - sizeof(feature_info)) + byref(vmb_feature_info), + sizeof(vmb_feature_info)) if error: raise VimbaException(error) - return feature_info + return vmb_feature_info def _get_int(self) -> int: value = c_int64() -- cgit v1.2.3 From b5431978c51107ba9e6475fc489fbd6dc7110332 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 16:32:59 +1100 Subject: clean up camera class --- pymba/vimba_camera.py | 138 ++++++++++++++++++-------------------------------- 1 file changed, 50 insertions(+), 88 deletions(-) diff --git a/pymba/vimba_camera.py b/pymba/vimba_camera.py index 5e131a1..27bd5d3 100644 --- a/pymba/vimba_camera.py +++ b/pymba/vimba_camera.py @@ -1,129 +1,91 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from . import vimba_structure as structs +from ctypes import byref, sizeof +from typing import Optional + from .vimba_object import VimbaObject from .vimba_exception import VimbaException from .vimba_frame import VimbaFrame -from .vimba_dll import VimbaDLL -from ctypes import * - -# camera features are automatically readable as object attributes. +from . import vimba_c class VimbaCamera(VimbaObject): - """ - A Vimba camera object. This class provides the minimal access - to Vimba functions required to control the camera. + A Vimba camera object. """ - @property - def cameraIdString(self): - return self._cameraIdString.decode() - - # own handle is inherited as self._handle - def __init__(self, cameraIdString): - - # call super constructor - super(VimbaCamera, self).__init__() + def __init__(self, id_string: str): + self._id_string = id_string.encode() + super().__init__() + self._info = self._get_info() - # set ID - self._cameraIdString = cameraIdString.encode() - - # set own info - self._info = self._getInfo() + @property + def id_string(self) -> str: + return self._id_string.decode() - def getInfo(self): + def _get_info(self) -> vimba_c.VmbCameraInfo: """ - Get info of the camera. Does not require - the camera to be opened. - - :returns: VimbaCameraInfo object -- camera information. + Get info of the camera. Does not require the camera to be opened. """ - return self._info + vmb_camera_info = vimba_c.VmbCameraInfo() + error = vimba_c.vmb_camera_info_query(self._id_string, + byref(vmb_camera_info), + sizeof(vmb_camera_info)) + if error: + raise VimbaException(error) - def _getInfo(self): - """ - Get info of the camera. Does not require - the camera to be opened. + return vmb_camera_info - :returns: VimbaCameraInfo object -- camera information. + def open(self, camera_access_mode: Optional[int] = VimbaObject.VMB_ACCESS_MODE_FULL): """ - # args for Vimba call - cameraInfo = structs.VimbaCameraInfo() - - # Vimba DLL will return an error code - errorCode = VimbaDLL.cameraInfoQuery(self._cameraIdString, - byref(cameraInfo), - sizeof(cameraInfo)) - if errorCode != 0: - raise VimbaException(errorCode) - - return cameraInfo - - def openCamera(self, cameraAccessMode=1): - """ - Open the camera with requested access mode - Available access modes: - 0 : VmbAccessModeNone - 1 : VmbAccessModeFull - 2 : VmbAccessModeRead - 3 : VmbAccessModeConfig - 4 : VmbAccessModeLite - """ - # args for Vimba call - errorCode = VimbaDLL.cameraOpen(self._cameraIdString, - cameraAccessMode, + Open the camera with requested access mode. + """ + error = vimba_c.vmb_camera_open(self._id_string, + camera_access_mode, byref(self._handle)) - if errorCode != 0: - raise VimbaException(errorCode) + if error: + raise VimbaException(error) - def closeCamera(self): + def close(self): """ Close the camera. """ - errorCode = VimbaDLL.cameraClose(self._handle) - if errorCode != 0: - raise VimbaException(errorCode) + error = vimba_c.vmb_camera_close(self._handle) + if error: + raise VimbaException(error) - def revokeAllFrames(self): + def revoke_all_frames(self): """ Revoke all frames assigned to the camera. """ - errorCode = VimbaDLL.frameRevokeAll(self._handle) - if errorCode != 0: - raise VimbaException(errorCode) + error = vimba_c.vmb_frame_revoke_all(self._handle) + if error: + raise VimbaException(error) - def startCapture(self): + def start_capture(self): """ Prepare the API for incoming frames. """ - errorCode = VimbaDLL.captureStart(self._handle) - if errorCode != 0: - raise VimbaException(errorCode) + error = vimba_c.vmb_capture_start(self._handle) + if error: + raise VimbaException(error) - def endCapture(self): + def end_capture(self): """ Stop the API from being able to receive frames. """ - errorCode = VimbaDLL.captureEnd(self._handle) - if errorCode != 0: - raise VimbaException(errorCode) + error = vimba_c.vmb_capture_end(self._handle) + if error: + raise VimbaException(error) - def flushCaptureQueue(self): + def flush_capture_queue(self): """ Flush the capture queue. """ - errorCode = VimbaDLL.captureQueueFlush(self._handle) - if errorCode != 0: - raise VimbaException(errorCode) + error = vimba_c.vmb_capture_queue_flush(self._handle) + if error: + raise VimbaException(error) - # method for easy frame creation - def getFrame(self): + def create_frame(self) -> VimbaFrame: """ - Creates and returns a new frame object. Multiple frames - per camera can therefore be returned. - - :returns: VimbaFrame object -- the new frame. + Creates and returns a new frame object. Multiple frames per camera can therefore be returned. """ return VimbaFrame(self) -- cgit v1.2.3 From e0ce826bf865a1f92a836e2c9ac9ab8d83be79aa Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 16:33:18 +1100 Subject: encode and decode id internally --- pymba/vimba_interface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pymba/vimba_interface.py b/pymba/vimba_interface.py index b2b8890..647aa44 100644 --- a/pymba/vimba_interface.py +++ b/pymba/vimba_interface.py @@ -12,12 +12,12 @@ class VimbaInterface(VimbaObject): """ def __init__(self, id_string: str): - self._id_string = id_string + self._id_string = id_string.encode() super().__init__() @property def id_string(self): - return self._id_string + return self._id_string.decode() def open(self): """ -- cgit v1.2.3 From 5698e2db62b3b02c32efc130357424ee7b1c0d4c Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 16:36:20 +1100 Subject: simplify system class --- pymba/vimba_system.py | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/pymba/vimba_system.py b/pymba/vimba_system.py index f4d0c54..407bef6 100644 --- a/pymba/vimba_system.py +++ b/pymba/vimba_system.py @@ -1,22 +1,9 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import from .vimba_object import VimbaObject -from ctypes import c_void_p - -# system features are automatically readable as attributes. class VimbaSystem(VimbaObject): - """ - A Vimba system object. This class provides the minimal access - to Vimba functions required to control the system. + A Vimba system object. This class provides the minimal access to Vimba functions required to control the system. """ - - # own handle is inherited as self._handle - def __init__(self): - super(VimbaSystem, self).__init__() - - # set own handle manually - self._handle = c_void_p(1) + super().__init__(handle=1) -- cgit v1.2.3 From 530d7b1ef415e8be19f03852f204851271edeb87 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 16:59:46 +1100 Subject: clean up vimba class --- pymba/vimba.py | 325 +++++++++++++++++++++++---------------------------------- 1 file changed, 131 insertions(+), 194 deletions(-) diff --git a/pymba/vimba.py b/pymba/vimba.py index 5656b7c..0d6c6b5 100644 --- a/pymba/vimba.py +++ b/pymba/vimba.py @@ -1,49 +1,30 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from . import vimba_structure as structs -from .vimba_dll import VimbaDLL +from ctypes import byref, sizeof, c_uint32 +from typing import List + from .vimba_exception import VimbaException from .vimba_system import VimbaSystem from .vimba_camera import VimbaCamera from .vimba_interface import VimbaInterface -from ctypes import * +from . import vimba_c class Vimba(object): - """ - An Allied Vision Technology Vimba API. - This API provides access to AVT cameras. + Python wrapper for Allied Vision's Vimba C API. """ - # todo - assign camera info and feature info as own object proeprties + # todo - assign camera info and feature info as own object properties def __init__(self): - # create own system singleton object self._system = VimbaSystem() - - # lists of VimbaCameraInfo and VimbaInterfaceInfo objects - # can't be called before startup() so populate later - self._interfaceInfos = None - - # dict of {camera ID : VimbaCamera object} as we don't want to forget - # them - self._cameras = {} - - # dict of {interface ID : VimbaInterface object} as we don't want to - # forget them + self._vmb_interface_infos = None self._interfaces = {} + self._cameras = {} def __enter__(self): """ Define vimba context for safe execution. - - The vimba object should be used like this: - # start Vimba - with Vimba() as vimba: - system = vimba.getSystem() - # ... """ self.startup() return self @@ -56,220 +37,176 @@ class Vimba(object): """ self.shutdown() - def _getInterfaceInfos(self): + @property + def system(self) -> VimbaSystem: """ - Gets interface info of all available interfaces. + Get the system object. + """ + return self._system + + @property + def version(self) -> str: + """ + Retrieve the version number of the Vimba C API. + """ + vmb_version_info = vimba_c.VmbVersionInfo() + error = vimba_c.vmb_version_query(vmb_version_info, sizeof(vmb_version_info)) + if error: + raise VimbaException(error) + + return '.'.join(str(x) for x in (vmb_version_info.major, + vmb_version_info.minor, + vmb_version_info.patch)) + + def startup(self): + """ + Initialize the Vimba C API. + """ + error = vimba_c.vmb_startup() + if error: + raise VimbaException(error) - :returns: list -- interface info for available interfaces. + def shutdown(self): """ - if self._interfaceInfos is None: - # args - numFound = c_uint32(-1) + Perform a shutdown on the API. + """ + vimba_c.vmb_shutdown() + + def _get_interface_infos(self) -> List[vimba_c.VmbInterfaceInfo]: + """ + Gets interface info of all available interfaces. + """ + + # todo is this caching required/harmful? + + if self._vmb_interface_infos is None: + num_found = c_uint32(-1) # call once just to get the number of interfaces - # Vimba DLL will return an error code - errorCode = VimbaDLL.interfacesList(None, + error = vimba_c.vmb_interfaces_list(None, 0, - byref(numFound), - sizeof(structs.VimbaInterfaceInfo)) - if errorCode != 0: - raise VimbaException(errorCode) + byref(num_found), + sizeof(vimba_c.VmbInterfaceInfo)) + if error: + raise VimbaException(error) - numInterfaces = numFound.value + # call again to get the features + num_interfaces = num_found.value + vmb_interface_infos = (vimba_c.VmbInterfaceInfo * num_interfaces)() + error = vimba_c.vmb_interfaces_list(vmb_interface_infos, + num_interfaces, + byref(num_found), + sizeof(vimba_c.VmbInterfaceInfo)) + if error: + raise VimbaException(error) - # args - interfaceInfoArray = (structs.VimbaInterfaceInfo * numInterfaces)() + self._vmb_interface_infos = list(vmb_interface_info for vmb_interface_info in vmb_interface_infos) - # call again to get the features - # Vimba DLL will return an error code - errorCode = VimbaDLL.interfacesList(interfaceInfoArray, - numInterfaces, - byref(numFound), - sizeof(structs.VimbaInterfaceInfo)) - if errorCode != 0: - raise VimbaException(errorCode) - self._interfaceInfos = list( - interfaceInfo for interfaceInfo in interfaceInfoArray) - return self._interfaceInfos + return self._vmb_interface_infos - def _getCameraInfos(self): + def _get_camera_infos(self) -> List[vimba_c.VmbCameraInfo]: """ Gets camera info of all attached cameras. - - :returns: list -- camera info for available cameras. """ - # args - dummyCameraInfo = structs.VimbaCameraInfo() - numFound = c_uint32(-1) + vmb_camera_info = vimba_c.VmbCameraInfo() + num_found = c_uint32(-1) # call once just to get the number of cameras - # Vimba DLL will return an error code - errorCode = VimbaDLL.camerasList(byref(dummyCameraInfo), + error = vimba_c.vmb_cameras_list(byref(vmb_camera_info), 0, - byref(numFound), - sizeof(dummyCameraInfo)) - if errorCode != 0 and errorCode != -9: - raise VimbaException(errorCode) + byref(num_found), + sizeof(vmb_camera_info)) + if error and error != -9: + raise VimbaException(error) - numCameras = numFound.value - - # args - cameraInfoArray = (structs.VimbaCameraInfo * numCameras)() + num_cameras = num_found.value # call again to get the features - # Vimba DLL will return an error code - errorCode = VimbaDLL.camerasList(cameraInfoArray, - numCameras, - byref(numFound), - sizeof(dummyCameraInfo)) - if errorCode != 0: - raise VimbaException(errorCode) - return list(camInfo for camInfo in cameraInfoArray) + vmb_camera_infos = (vimba_c.VmbCameraInfo * num_cameras)() + error = vimba_c.vmb_cameras_list(vmb_camera_infos, + num_cameras, + byref(num_found), + sizeof(vmb_camera_info)) + if error: + raise VimbaException(error) + return list(vmb_camera_info for vmb_camera_info in vmb_camera_infos) - def getSystem(self): - """ - Gets system singleton object. - - :returns: VimbaSystem object -- the system singleton object. - """ - return self._system - - def getInterfaceIds(self): + def get_interface_ids(self) -> List[str]: """ Gets IDs of all available interfaces. - - :returns: list -- interface IDs for available interfaces. """ - return list(interfaceInfo.interfaceIdString for interfaceInfo in self._getInterfaceInfos()) + return list(vmb_interface_info.id_string for vmb_interface_info in self._get_interface_infos()) - def getCameraIds(self): + def get_camera_ids(self) -> List[str]: """ Gets IDs of all available cameras. - - :returns: list -- camera IDs for available cameras. """ - return list(camInfo.cameraIdString.decode() for camInfo in self._getCameraInfos()) + return list(camera_info.id_string.decode() for camera_info in self._get_camera_infos()) - def getInterfaceInfo(self, interfaceId): + def _get_interface_info(self, id_string: str) -> vimba_c.VmbInterfaceInfo: """ Gets interface info object of specified interface. - - :param interfaceId: the ID of the interface object to get. - - :returns: VimbaInterfaceInfo object -- the interface info object specified. + :param id_string: the ID of the interface object to get. """ # don't do this live as we already have this info # return info object if it exists - for interfaceInfo in self._getInterfaceInfos(): - if interfaceInfo.interfaceIdString == interfaceId: - return interfaceInfo - # otherwise raise error - raise VimbaException(-54) + for vmb_interface_info in self._get_interface_infos(): - def getCameraInfo(self, cameraId): - """ - Gets camera info object of specified camera. + # todo broken lookup on info objects - :param cameraId: the ID of the camera object to get. - This might not only be a cameraId as returned by getCameraIds() - but also e.g. a serial number. Check the Vimba documentation for - other possible values. + if vmb_interface_info.id_string == id_string: + return vmb_interface_info + raise VimbaException(VimbaException.ERR_INTERFACE_NOT_FOUND) - :returns: VimbaCameraInfo object -- the camera info object specified. + def _get_camera_info(self, id_string: str) -> vimba_c.VmbCameraInfo: """ - cameraInfo = structs.VimbaCameraInfo() - errorCode = VimbaDLL.cameraInfoQuery(cameraId.encode(), - cameraInfo, - sizeof(cameraInfo)) - if errorCode == 0: - return cameraInfo - - # otherwise raise error - raise VimbaException(-50) - - def getInterface(self, interfaceId): + Gets camera info object of specified camera. + :param cameraId: the ID of the camera object to get. This can be an ID or e.g. a serial number. Check the Vimba + documentation for other possible values. """ - Gets interface object based on interface ID string. Will not recreate - interface object if it already exists. + vmb_camera_info = vimba_c.VmbCameraInfo() + error = vimba_c.vmb_camera_info_query(id_string.encode(), + vmb_camera_info, + sizeof(vmb_camera_info)) + if error: + raise VimbaException(error) + return vmb_camera_info - :param interfaceId: the ID of the interface. - - :returns: VimbaInterface object -- the interface object specified. + def get_interface(self, id_string) -> VimbaInterface: + """ + Gets interface object based on interface ID string. Will not recreate interface object if it already exists. + :param id_string: the ID of the interface. """ # check ID is valid - if interfaceId in self.getInterfaceIds(): + if id_string in self.get_interface_ids(): # create it if it doesn't exist - if interfaceId not in self._interfaces: - self._interfaces[interfaceId] = VimbaInterface(interfaceId) - return self._interfaces[interfaceId] - raise VimbaException(-54) + if id_string not in self._interfaces: + self._interfaces[id_string] = VimbaInterface(id_string) + return self._interfaces[id_string] + raise VimbaException(VimbaException.ERR_INTERFACE_NOT_FOUND) - def getCamera(self, cameraId): + def get_camera(self, camera_id: str) -> VimbaCamera: """ - Gets camera object based on camera ID string. Will not recreate - camera object if it already exists. - - :param cameraId: the ID of the camera object to get. - This might not only be a cameraId as returned by getCameraIds() - but also e.g. a serial number. Check the Vimba documentation for - other possible values. - - :returns: VimbaCamera object -- the camera object specified. + Gets camera object based on camera ID string. Will not recreate camera object if it already exists. + :param camera_id: the ID of the camera object to get. This can be an ID or e.g. a serial number. Check the Vimba + documentation for other possible values. """ # check ID is valid - if cameraId in self.getCameraIds(): + if camera_id in self.get_camera_ids(): # create it if it doesn't exist - if cameraId not in self._cameras: - self._cameras[cameraId] = VimbaCamera(cameraId) - return self._cameras[cameraId] + if camera_id not in self._cameras: + self._cameras[camera_id] = VimbaCamera(camera_id) + return self._cameras[camera_id] else: # the given string might not be a camera ID -> check for other IDs - cameraInfo = structs.VimbaCameraInfo() - errorCode = VimbaDLL.cameraInfoQuery(cameraId.encode(), - cameraInfo, - sizeof(cameraInfo)) - if errorCode != 0: - raise VimbaException(-50) # camera not found + vmb_camera_info = vimba_c.VmbCameraInfo() + error = vimba_c.vmb_camera_info_query(camera_id.encode(), + vmb_camera_info, + sizeof(vmb_camera_info)) + if error: + raise VimbaException(error) - cameraIdString = cameraInfo.cameraIdString.decode() - if cameraIdString not in self._cameras: - self._cameras[cameraIdString] = VimbaCamera(cameraIdString) - return self._cameras[cameraIdString] - - - def getVersion(self): - """ - Retrieve the version number of VimbaC. - - :returns: string - Vimba API version info. - """ - # args - versionInfo = structs.VimbaVersion() - - # Vimba DLL will return an error code - errorCode = VimbaDLL.versionQuery( - versionInfo, - sizeof(versionInfo) - ) - if errorCode: - raise VimbaException(errorCode) - - versionStr = '.'.join([str(versionInfo.major), - str(versionInfo.minor), - str(versionInfo.patch)]) - return versionStr - - def startup(self): - """ - Initialize the VimbaC API. - """ - # Vimba DLL will return an error code - errorCode = VimbaDLL.startup() - if errorCode != 0: - raise VimbaException(errorCode) - - def shutdown(self): - """ - Perform a shutdown on the API. - """ - VimbaDLL.shutdown() + camera_id_string = vmb_camera_info.id_string.decode() + if camera_id_string not in self._cameras: + self._cameras[camera_id_string] = VimbaCamera(camera_id_string) + return self._cameras[camera_id_string] -- cgit v1.2.3 From d43df422628b8b346383245d7cb029b465f6e900 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 17:00:37 +1100 Subject: clean up __init__ --- pymba/__init__.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pymba/__init__.py b/pymba/__init__.py index c21ed07..7ade159 100644 --- a/pymba/__init__.py +++ b/pymba/__init__.py @@ -1,5 +1,2 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import from .vimba import Vimba from .vimba_exception import VimbaException - -- cgit v1.2.3 From 040c207c3722c0a92e4ab99c4cf3f1b2e937fa2f Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 17:15:41 +1100 Subject: clean up vimba object class --- pymba/vimba_object.py | 246 ++++++++++++++++++++++---------------------------- 1 file changed, 110 insertions(+), 136 deletions(-) diff --git a/pymba/vimba_object.py b/pymba/vimba_object.py index 5f1cead..7199e61 100644 --- a/pymba/vimba_object.py +++ b/pymba/vimba_object.py @@ -1,34 +1,40 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from . import vimba_structure as structs +from ctypes import byref, sizeof, c_void_p, c_uint32, c_uint64, c_bool +from typing import Union, Tuple, List, Optional + from .vimba_exception import VimbaException from .vimba_feature import VimbaFeature -from .vimba_dll import VimbaDLL -from ctypes import * +from . import vimba_c -class VimbaObject(object): +class VimbaObject: """ - A Vimba object has a handle and features associated with it. - Objects include System, Camera, Interface and AncillaryData. + A Vimba object has a handle and features associated with it. Objects include System, Camera, Interface and + AncillaryData. Features are automatically readable as instance attributes. """ + + VMB_ACCESS_MODE_NONE = 0 + VMB_ACCESS_MODE_FULL = 1 + VMB_ACCESS_MODE_READ = 2 + VMB_ACCESS_MODE_CONFIG = 4 + VMB_ACCESS_MODE_LITE = 8 + + def __init__(self, handle: Optional[int] = None): + if handle is None: + self._handle = c_void_p() + else: + self._handle = c_void_p(handle) + + # can't be populated until device is opened + self._vmb_features_info = None + @property def handle(self): return self._handle - def __init__(self): - # create own handle - self._handle = c_void_p() - - # list of VimbaFeatureInfo objects can't set yet as the object (e.g. a camera) won't be opened yet, therefore - # no event for object opening so will have it populate by user interaction and blame them if the object is not - # opened then - self._featureInfos = None - # override getattr for undefined attributes def __getattr__(self, attr): # if a feature value requested (requires object (camera) open) - if attr in self.getFeatureNames(): + if attr in self.get_feature_names(): return VimbaFeature(attr, self._handle).value # otherwise don't know about it @@ -44,14 +50,14 @@ class VimbaObject(object): super(VimbaObject, self).__setattr__(attr, val) # if it's an actual camera feature (requires camera open) - elif attr in self.getFeatureNames(): + elif attr in self.get_feature_names(): VimbaFeature(attr, self._handle).value = val # otherwise just set the attribute value as normal else: super(VimbaObject, self).__setattr__(attr, val) - def _getFeatureInfos(self): + def _get_feature_infos(self) -> List[vimba_c.VmbFeatureInfo]: """ Gets feature info of all available features. Will cause error if object/camera is not opened. @@ -59,170 +65,138 @@ class VimbaObject(object): :returns: list -- feature info for available features. """ # check it's populated as can't populate it in __init__ - if self._featureInfos is None: - # args - dummyFeatureInfo = structs.VimbaFeatureInfo() - numFound = c_uint32(-1) + if self._vmb_features_info is None: + vmb_feature_info = vimba_c.VmbFeatureInfo() + num_found = c_uint32(-1) # call once to get number of available features - # Vimba DLL will return an error code - errorCode = VimbaDLL.featuresList(self._handle, + error = vimba_c.vmb_features_list(self._handle, None, 0, - byref(numFound), - sizeof(dummyFeatureInfo)) - if errorCode != 0: - raise VimbaException(errorCode) + byref(num_found), + sizeof(vmb_feature_info)) + if error: + raise VimbaException(error) # number of features specified by Vimba - numFeatures = numFound.value - - # args - featureInfoArray = (structs.VimbaFeatureInfo * numFeatures)() + num_features = num_found.value + vmb_feature_infos = (vimba_c.VmbFeatureInfo * num_features)() # call again to get the features - # Vimba DLL will return an error code - errorCode = VimbaDLL.featuresList(self._handle, - featureInfoArray, - numFeatures, - byref(numFound), - sizeof(dummyFeatureInfo)) - if errorCode != 0: - raise VimbaException(errorCode) - - self._featureInfos = list( - featInfo for featInfo in featureInfoArray) - return self._featureInfos - - def getFeatureNames(self): + error = vimba_c.vmb_features_list(self._handle, + vmb_feature_infos, + num_features, + byref(num_found), + sizeof(vmb_feature_info)) + if error: + raise VimbaException(error) + + self._vmb_features_info = list(vmb_feature_info for vmb_feature_info in vmb_feature_infos) + + return self._vmb_features_info + + def get_feature_names(self) -> List[str]: """ Get names of all available features. - - :returns: list -- feature names for available features. """ - return list(featInfo.name.decode() for featInfo in self._getFeatureInfos()) + return list(feature_info.name for feature_info in self._get_feature_infos()) - def getFeatureInfo(self, featureName): + def get_feature_info(self, feature_name: str) -> vimba_c.VmbFeatureInfo: """ Gets feature info object of specified feature. - - :param featureName: the name of the feature. - - :returns: VimbaFeatureInfo object -- the feature info object specified. + :param feature_name: the name of the feature. """ # don't do this live as we already have this info # return info object, if it exists - for featInfo in self._getFeatureInfos(): - if featInfo.name.decode() == featureName: - return featInfo + for vmb_feature_info in self._get_feature_infos(): + if vmb_feature_info.name == feature_name: + return vmb_feature_info # otherwise raise error - raise VimbaException(-53) + raise VimbaException(VimbaException.ERR_FEATURE_NOT_FOUND) # don't think we ever need to return a feature object... # def getFeature(self, featureName): - def getFeatureRange(self, featureName): + def get_feature_range(self, feature_name: str) -> Union[Tuple[float, float], Tuple[int, int], List[str]]: """ Get valid range of feature values. - - :param featureName: name of the feature to query. - + :param feature_name: name of the feature to query. :returns: tuple -- range as (feature min value, feature max value, for int or float features only). list -- names of possible enum values (for enum features only). """ - # can't cache this, need to look it up live - return VimbaFeature(featureName, self._handle).range + # shouldn't cache this + return VimbaFeature(feature_name, self._handle).range - def runFeatureCommand(self, featureName): + def run_feature_command(self, feature_name: str) -> None: """ Run a feature command. - - :param featureName: the name of the feature. + :param feature_name: the name of the feature. """ # run a command - errorCode = VimbaDLL.featureCommandRun( - self._handle, - featureName.encode() - ) - if errorCode != 0: - raise VimbaException(errorCode) - - def featureCommandIsDone(self, featureName): - isDone = c_bool() - errorCode = VimbaDLL.featureCommandIsDone( - self._handle, - featureName.encode(), - byref(isDone) - ) - - if errorCode != 0: - raise VimbaException(errorCode) - - return isDone.value - - def readRegister(self, address): + error = vimba_c.vmb_feature_command_run(self._handle, + feature_name.encode()) + if error: + raise VimbaException(error) + + def feature_command_is_done(self, feature_name: str) -> bool: + is_done = c_bool() + error = vimba_c.vmb_feature_command_is_done(self._handle, + feature_name.encode(), + byref(is_done)) + if error: + raise VimbaException(error) + + return is_done.value + + def read_register(self, address: int) -> int: # note that the underlying Vimba function allows reading of an array # of registers, but only one address/value at a time is implemented # here """ - Read from a register of the module (camera). - + Read from a register of the module (camera) and return its value. :param address: the address of the register to read. - - :returns: int -- value of register. """ - readCount = 1 + read_count = 1 - # check address validity - try: - regAddress = c_uint64(int(address, 16)) - except: - raise VimbaException(-52) + # todo expects bytes not int - regData = c_uint64() - numCompleteReads = c_uint32() + reg_address = c_uint64(int(address, 16)) - errorCode = VimbaDLL.registersRead(self.handle, - readCount, - byref(regAddress), - byref(regData), - byref(numCompleteReads)) + reg_data = c_uint64() + num_complete_reads = c_uint32() - if errorCode != 0: - raise VimbaException(errorCode) + error = vimba_c.vmb_registers_read(self.handle, + read_count, + byref(reg_address), + byref(reg_data), + byref(num_complete_reads)) + if error: + raise VimbaException(error) - return regData.value + return reg_data.value - def writeRegister(self, address, value): + def write_register(self, address: int, value: int) -> None: # note that the underlying Vimba function allows writing of an array # of registers, but only one address/value at a time is implemented # here """ - Read from a register of the module (camera). - + Write to a register of the module (camera). :param address: the address of the register to read. :param value: the value to set in hex. """ - writeCount = 1 - - # check address validity - try: - regAddress = c_uint64(int(address, 16)) - except: - raise VimbaException(-52) - - # check value validity - try: - regData = c_uint64(int(value, 16)) - except: - raise VimbaException(-52) - - numCompleteWrites = c_uint32() - - errorCode = VimbaDLL.registersWrite(self.handle, - writeCount, - byref(regAddress), - byref(regData), - byref(numCompleteWrites)) - if errorCode != 0: - raise VimbaException(errorCode) + write_count = 1 + + # todo expects bytes not int + + reg_address = c_uint64(int(address, 16)) + reg_data = c_uint64(int(value, 16)) + + num_complete_writes = c_uint32() + + error = vimba_c.vmb_registers_write(self.handle, + write_count, + byref(reg_address), + byref(reg_data), + byref(num_complete_writes)) + if error: + raise VimbaException(error) -- cgit v1.2.3 From fcf34f86abce5a002babc4f7a3e465f312c7f61b Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 17:15:58 +1100 Subject: function rename --- examples/list_cameras.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/list_cameras.py b/examples/list_cameras.py index 0be2e12..1d8258c 100644 --- a/examples/list_cameras.py +++ b/examples/list_cameras.py @@ -7,6 +7,6 @@ if __name__ == '__main__': with Vimba() as vmb: # required for discovering GigE cameras if vmb.system.GeVTLIsPresent: - vmb.system.runFeatureCommand("GeVDiscoveryAllOnce") + vmb.system.run_feature_command("GeVDiscoveryAllOnce") sleep(0.2) print(vmb.camera_ids) -- cgit v1.2.3 From 8f851759ecfe7b874020cbe4297f32a80993296a Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 22 Jan 2019 17:17:44 +1100 Subject: clean up C function and structure definitions --- pymba/vimba_frame.py | 53 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/pymba/vimba_frame.py b/pymba/vimba_frame.py index 8cf0c86..2cd8492 100644 --- a/pymba/vimba_frame.py +++ b/pymba/vimba_frame.py @@ -1,9 +1,8 @@ -# -*- coding: utf-8 -*- from __future__ import absolute_import from . import vimba_structure as structs from .vimba_exception import VimbaException -from .vimba_dll import VimbaDLL -from .vimba_dll import VimbaC_MemoryBlock +from .vimba_c import VimbaDLL +from .vimba_c import VimbaC_MemoryBlock from ctypes import * import warnings try: @@ -12,14 +11,12 @@ except ImportError: warnings.warn('numpy not found, some VimbaFrame methods will not be available') -""" -Map pixel formats to bytes per pixel. - The packed formats marked with "?" have not been tested. -""" +# Map pixel formats to bytes per pixel. PIXEL_FORMATS = { "Mono8": 1, "Mono12": 2, - "Mono12Packed": 1.5, # ? + # untested + "Mono12Packed": 1.5, "Mono14": 2, "Mono16": 2, "RGB8": 3, @@ -27,14 +24,16 @@ PIXEL_FORMATS = { "BGR8Packed": 3, "RGBA8Packed": 4, "BGRA8Packed": 4, - "YUV411Packed": 4/3.0, # ? + # untested + "YUV411Packed": 4 / 3.0, "YUV422Packed": 2, "YUV444Packed": 3, "BayerRG8": 1, "BayerRG12": 2, "BayerGR8": 1, "BayerGR12": 2, - "BayerGR12Packed": 1.5, # ? + # untested + "BayerGR12Packed": 1.5, } @@ -68,29 +67,29 @@ class VimbaFrame(object): sizeOfFrame = self.payloadSize # keep this reference to keep block alive for life of frame - self._cMem = VimbaC_MemoryBlock(sizeOfFrame) + self._c_mem = VimbaC_MemoryBlock(sizeOfFrame) # set buffer to have length of expected payload size - self._frame.buffer = self._cMem.block + self._frame.buffer = self._c_mem.block # set buffer size to expected payload size self._frame.bufferSize = sizeOfFrame - errorCode = VimbaDLL.frameAnnounce(self._handle, + error = VimbaDLL.frameAnnounce(self._handle, byref(self._frame), sizeof(self._frame)) - if errorCode != 0: - raise VimbaException(errorCode) + if error: + raise VimbaException(error) def revokeFrame(self): """ Revoke a frame from the API. """ - errorCode = VimbaDLL.frameRevoke(self._handle, + error = VimbaDLL.frameRevoke(self._handle, byref(self._frame)) - if errorCode != 0: - raise VimbaException(errorCode) + if error: + raise VimbaException(error) def queueFrameCapture(self, frameCallback = None): """ @@ -119,15 +118,15 @@ class VimbaFrame(object): # keep a reference to prevent gc issues self._frameCallbackWrapper_C = VimbaDLL.frameDoneCallback(frameCallbackWrapper) - errorCode = VimbaDLL.captureFrameQueue(self._handle, + error = VimbaDLL.captureFrameQueue(self._handle, byref(self._frame), self._frameCallbackWrapper_C) - if errorCode != 0: - raise VimbaException(errorCode) + if error: + raise VimbaException(error) def waitFrameCapture(self, timeout=2000): """ - Wait for a queued frame to be filled (or dequeued). Returns Errorcode + Wait for a queued frame to be filled (or dequeued). Returns error upon completion. Runs VmbCaptureFrameWait @@ -135,16 +134,16 @@ class VimbaFrame(object): Call after an acquisition command """ - errorCode = VimbaDLL.captureFrameWait(self._handle, + error = VimbaDLL.captureFrameWait(self._handle, byref(self._frame), timeout) - # errorCode to be processed by the end user for this function. + # error to be processed by the end user for this function. # Prevents system for breaking for example on a hardware trigger # timeout - #if errorCode != 0: - #raise VimbaException(errorCode) - return errorCode + #if error: + #raise VimbaException(error) + return error # custom method for simplified usage def getBufferByteData(self): -- cgit v1.2.3 From 058cd5c653f09dc0308d259017c2a0b2195c8749 Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 23 Jan 2019 14:20:05 +1100 Subject: clean up frame class --- pymba/vimba_frame.py | 162 +++++++++++++++++++++++++-------------------------- 1 file changed, 79 insertions(+), 83 deletions(-) diff --git a/pymba/vimba_frame.py b/pymba/vimba_frame.py index 2cd8492..0832429 100644 --- a/pymba/vimba_frame.py +++ b/pymba/vimba_frame.py @@ -1,14 +1,14 @@ -from __future__ import absolute_import -from . import vimba_structure as structs -from .vimba_exception import VimbaException -from .vimba_c import VimbaDLL -from .vimba_c import VimbaC_MemoryBlock -from ctypes import * +from ctypes import byref, sizeof, addressof, create_string_buffer, cast, POINTER, c_ubyte, c_void_p +from typing import Optional import warnings try: import numpy as np except ImportError: - warnings.warn('numpy not found, some VimbaFrame methods will not be available') + warnings.warn('could not import numpy, some Frame methods may not work.') + +from .vimba_camera import VimbaCamera +from .vimba_exception import VimbaException +from . import vimba_c # Map pixel formats to bytes per pixel. @@ -37,143 +37,139 @@ PIXEL_FORMATS = { } -class VimbaFrame(object): +class MemoryBlock: + """ + A memory block object for dealing neatly with C memory allocations. + """ + + @property + def block(self): + return c_void_p(addressof(self._block)) + + def __init__(self, block_size): + self._block = create_string_buffer(block_size) + + # this seems to be None if too much memory is requested + if self._block is None: + raise VimbaException(VimbaException.ERR_FRAME_BUFFER_MEMORY) + + def __del__(self): + del self._block + + +class Frame: """ A Vimba frame. """ - def __init__(self, camera): + + def __init__(self, camera: VimbaCamera): self._camera = camera self._handle = camera.handle # get frame sizes - self.payloadSize = self._camera.PayloadSize + self.payload_size = self._camera.PayloadSize self.width = self._camera.Width self.height = self._camera.Height self.pixel_bytes = PIXEL_FORMATS[self._camera.PixelFormat] # frame structure - self._frame = structs.VimbaFrame() + self._frame = vimba_c.VmbFrame() - def announceFrame(self): - """ - Announce frames to the API that may be queued for frame capturing later. - - Runs VmbFrameAnnounce + self._c_mem = None - Should be called after the frame is created. Call startCapture - after this method. + def announce(self): + """ + Announce frames to the API that may be queued for frame capturing later. Should be called after the frame is + created. Call startCapture after this method. """ - # size of expected frame - sizeOfFrame = self.payloadSize - # keep this reference to keep block alive for life of frame - self._c_mem = VimbaC_MemoryBlock(sizeOfFrame) + self._c_mem = MemoryBlock(self.payload_size) # set buffer to have length of expected payload size self._frame.buffer = self._c_mem.block # set buffer size to expected payload size - self._frame.bufferSize = sizeOfFrame + self._frame.bufferSize = self.payload_size - error = VimbaDLL.frameAnnounce(self._handle, + error = vimba_c.vmb_frame_announce(self._handle, byref(self._frame), sizeof(self._frame)) - if error: raise VimbaException(error) - def revokeFrame(self): + def revoke(self): """ Revoke a frame from the API. """ - error = VimbaDLL.frameRevoke(self._handle, + error = vimba_c.vmb_frame_revoke(self._handle, byref(self._frame)) - if error: raise VimbaException(error) - def queueFrameCapture(self, frameCallback = None): + def queue_capture(self, frame_callback: Optional[bool] = None) -> None: """ - Queue frames that may be filled during frame capturing. - Runs VmbCaptureFrameQueue - - Call after announceFrame and startCapture - - Callback must accept argument of type frame. Remember to requeue the - frame by calling frame.queueFrameCapture(frameCallback) at the end of - your callback function. + Queue frames that may be filled during frame capturing. Call after announceFrame and startCapture. Callback + must accept argument of type frame. Remember to requeue the frame by calling frame.queue_capture() at the end + of your callback function. """ - # remember the given callback function - self._frameCallback = frameCallback + self._frame_callback = frame_callback # define a callback wrapper here so it doesn't bind self - def frameCallbackWrapper(cam_handle, p_frame): + def frame_callback_wrapper(cam_handle, p_frame): # call the user's callback with the self bound outside the wrapper # ignore the frame pointer since we already know the callback # refers to this frame - self._frameCallback(self) + self._frame_callback(self) - if self._frameCallback is None: - self._frameCallbackWrapper_C = None + if self._frame_callback is None: + self._frame_callback_wrapper_c = None else: # keep a reference to prevent gc issues - self._frameCallbackWrapper_C = VimbaDLL.frameDoneCallback(frameCallbackWrapper) + self._frame_callback_wrapper_c = vimba_c.vmb_frame_callback(frame_callback_wrapper) - error = VimbaDLL.captureFrameQueue(self._handle, - byref(self._frame), - self._frameCallbackWrapper_C) + error = vimba_c.vmb_capture_frame_queue(self._handle, + byref(self._frame), + self._frame_callback_wrapper_c) if error: raise VimbaException(error) - def waitFrameCapture(self, timeout=2000): + def wait_capture(self, timeout_ms: Optional[int] = 2000) -> int: """ - Wait for a queued frame to be filled (or dequeued). Returns error - upon completion. - Runs VmbCaptureFrameWait - - timeout - int, milliseconds default(timeout, 2000) - - Call after an acquisition command + Wait for a queued frame to be filled (or dequeued). Call after an acquisition command. + :param timeout_ms: time out in milliseconds. """ - error = VimbaDLL.captureFrameWait(self._handle, - byref(self._frame), - timeout) + error = vimba_c.vmb_capture_frame_wait(self._handle, + byref(self._frame), + timeout_ms) # error to be processed by the end user for this function. - # Prevents system for breaking for example on a hardware trigger - # timeout - #if error: - #raise VimbaException(error) + # Prevents system for breaking for example on a hardware trigger timeout + + # todo raise error instead? + return error - # custom method for simplified usage - def getBufferByteData(self): + def get_buffer_data(self) -> c_ubyte * int: """ Retrieve buffer data in a useful format. - - :returns: array -- buffer data. """ - # cast frame buffer memory contents to a usable type - data = cast(self._frame.buffer, - POINTER(c_ubyte * self.payloadSize)) + data = cast(self._frame.buffer, POINTER(c_ubyte * self.payload_size)) # make array of c_ubytes from buffer - imagebytes = int(self.height * self.width * self.pixel_bytes) - array = (c_ubyte * imagebytes).from_address(addressof(data.contents)) + image_bytes = int(self.height * self.width * self.pixel_bytes) + return (c_ubyte * image_bytes).from_address(addressof(data.contents)) - return array - - def getImage(self): - cframe = self._frame - data = cast(cframe.buffer, POINTER(c_ubyte * cframe.imageSize)) - try: - return np.ndarray(buffer=data.contents, dtype=np.uint8, shape=(cframe.height, cframe.width)) - except NameError as e: - print('install numpy to use this method or use getBufferByteData instead') - raise e + def get_image(self) -> np.ndarray: + """ + Returns the frame's image data as a NumPy array. + """ + data = cast(self._frame.buffer, POINTER(c_ubyte * self._frame.imageSize)) + return np.ndarray(buffer=data.contents, dtype=np.uint8, shape=(self._frame.height, self._frame.width)) - def getTimestamp(self): + @property + def timestamp(self) -> int: return self._frame.timestamp - def getReceiveStatus(self): + @property + def receive_status(self) -> int: return self._frame.receiveStatus -- cgit v1.2.3 From d26f4f736dde31d0a651a97500c63023578ed862 Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 23 Jan 2019 14:24:27 +1100 Subject: simplify file names --- pymba/camera.py | 91 +++++++++++++++++++ pymba/feature.py | 225 +++++++++++++++++++++++++++++++++++++++++++++++ pymba/frame.py | 175 ++++++++++++++++++++++++++++++++++++ pymba/interface.py | 37 ++++++++ pymba/system.py | 9 ++ pymba/vimba.py | 20 ++--- pymba/vimba_c.py | 22 ----- pymba/vimba_camera.py | 91 ------------------- pymba/vimba_feature.py | 225 ----------------------------------------------- pymba/vimba_frame.py | 175 ------------------------------------ pymba/vimba_interface.py | 37 -------- pymba/vimba_object.py | 8 +- pymba/vimba_system.py | 9 -- 13 files changed, 551 insertions(+), 573 deletions(-) create mode 100644 pymba/camera.py create mode 100644 pymba/feature.py create mode 100644 pymba/frame.py create mode 100644 pymba/interface.py create mode 100644 pymba/system.py delete mode 100644 pymba/vimba_camera.py delete mode 100644 pymba/vimba_feature.py delete mode 100644 pymba/vimba_frame.py delete mode 100644 pymba/vimba_interface.py delete mode 100644 pymba/vimba_system.py diff --git a/pymba/camera.py b/pymba/camera.py new file mode 100644 index 0000000..16910fb --- /dev/null +++ b/pymba/camera.py @@ -0,0 +1,91 @@ +from ctypes import byref, sizeof +from typing import Optional + +from .vimba_object import VimbaObject +from .vimba_exception import VimbaException +from .frame import Frame +from . import vimba_c + + +class Camera(VimbaObject): + """ + A Vimba camera object. + """ + + def __init__(self, id_string: str): + self._id_string = id_string.encode() + super().__init__() + self._info = self._get_info() + + @property + def id_string(self) -> str: + return self._id_string.decode() + + def _get_info(self) -> vimba_c.VmbCameraInfo: + """ + Get info of the camera. Does not require the camera to be opened. + """ + vmb_camera_info = vimba_c.VmbCameraInfo() + error = vimba_c.vmb_camera_info_query(self._id_string, + byref(vmb_camera_info), + sizeof(vmb_camera_info)) + if error: + raise VimbaException(error) + + return vmb_camera_info + + def open(self, camera_access_mode: Optional[int] = VimbaObject.VMB_ACCESS_MODE_FULL): + """ + Open the camera with requested access mode. + """ + error = vimba_c.vmb_camera_open(self._id_string, + camera_access_mode, + byref(self._handle)) + if error: + raise VimbaException(error) + + def close(self): + """ + Close the camera. + """ + error = vimba_c.vmb_camera_close(self._handle) + if error: + raise VimbaException(error) + + def revoke_all_frames(self): + """ + Revoke all frames assigned to the camera. + """ + error = vimba_c.vmb_frame_revoke_all(self._handle) + if error: + raise VimbaException(error) + + def start_capture(self): + """ + Prepare the API for incoming frames. + """ + error = vimba_c.vmb_capture_start(self._handle) + if error: + raise VimbaException(error) + + def end_capture(self): + """ + Stop the API from being able to receive frames. + """ + error = vimba_c.vmb_capture_end(self._handle) + if error: + raise VimbaException(error) + + def flush_capture_queue(self): + """ + Flush the capture queue. + """ + error = vimba_c.vmb_capture_queue_flush(self._handle) + if error: + raise VimbaException(error) + + def create_frame(self) -> Frame: + """ + Creates and returns a new frame object. Multiple frames per camera can therefore be returned. + """ + return Frame(self) diff --git a/pymba/feature.py b/pymba/feature.py new file mode 100644 index 0000000..f81ea6a --- /dev/null +++ b/pymba/feature.py @@ -0,0 +1,225 @@ +from ctypes import byref, sizeof, c_uint32, c_double, c_char_p, c_bool, c_int64, create_string_buffer +from typing import Tuple, List + +from .vimba_exception import VimbaException +from . import vimba_c + + +class Feature: + """ + A feature of a Vimba object. + """ + + ( + _FEATURE_DATA_UNKNOWN, + _FEATURE_DATA_INT, + _FEATURE_DATA_FLOAT, + _FEATURE_DATA_ENUM, + _FEATURE_DATA_STRING, + _FEATURE_DATA_BOOL, + _FEATURE_DATA_COMMAND, + _FEATURE_DATA_RAW, + _FEATURE_DATA_NONE, + ) = range(9) + + @property + def name(self): + return self._name.decode() + + @property + def handle(self): + return self._handle + + # lookup relevant function for feature type and pass to that function + @property + def value(self): + return self._feature_data_value_funcs[self._info.featureDataType][0]() + + @value.setter + def value(self, val): + self._feature_data_value_funcs[self._info.featureDataType][1](val) + + @property + def range(self): + return self._feature_data_range_funcs[self._info.featureDataType]() + + def __init__(self, name, handle): + self._name = name.encode() + self._handle = handle + + # type functions dict for looking up correct get/set function to use + self._feature_data_value_funcs = { + self._FEATURE_DATA_UNKNOWN: None, + self._FEATURE_DATA_INT: (self._get_int, self._set_int), + self._FEATURE_DATA_FLOAT: (self._get_float, self._set_float), + self._FEATURE_DATA_ENUM: (self._get_enum, self._set_enum), + self._FEATURE_DATA_STRING: (self._get_string, self._set_string), + self._FEATURE_DATA_BOOL: (self._get_bool, self._set_bool), + self._FEATURE_DATA_COMMAND: None, + self._FEATURE_DATA_RAW: None, + self._FEATURE_DATA_NONE: None, + } + + # type functions dict for looking up correct range function to use + self._feature_data_range_funcs = { + self._FEATURE_DATA_UNKNOWN: None, + self._FEATURE_DATA_INT: self._range_query_int, + self._FEATURE_DATA_FLOAT: self._range_query_float, + self._FEATURE_DATA_ENUM: self._range_query_enum, + self._FEATURE_DATA_STRING: None, + self._FEATURE_DATA_BOOL: None, + self._FEATURE_DATA_COMMAND: None, + self._FEATURE_DATA_RAW: None, + self._FEATURE_DATA_NONE: None, + } + + # get info once + self._info = self._get_info() + + def _get_info(self) -> vimba_c.VmbFeatureInfo: + vmb_feature_info = vimba_c.VmbFeatureInfo() + error = vimba_c.vmb_feature_info_query(self._handle, + self._name, + byref(vmb_feature_info), + sizeof(vmb_feature_info)) + if error: + raise VimbaException(error) + + return vmb_feature_info + + def _get_int(self) -> int: + value = c_int64() + error = vimba_c.vmb_feature_int_get(self._handle, + self._name, + byref(value)) + if error: + raise VimbaException(error) + + return value.value + + def _set_int(self, value: int) -> None: + error = vimba_c.vmb_feature_int_set(self._handle, + self._name, + value) + if error: + raise VimbaException(error) + + def _get_float(self) -> float: + value = c_double() + error = vimba_c.vmb_feature_float_get(self._handle, + self._name, + byref(value)) + if error: + raise VimbaException(error) + + return value.value + + def _set_float(self, value: float) -> None: + error = vimba_c.vmb_feature_float_set(self._handle, + self._name, + value) + if error: + raise VimbaException(error) + + def _get_enum(self) -> str: + value = c_char_p() + error = vimba_c.vmb_feature_enum_get(self._handle, + self._name, + byref(value)) + if error: + raise VimbaException(error) + + return value.value.decode() + + def _set_enum(self, value: str): + error = vimba_c.vmb_feature_enum_set(self._handle, + self._name, + value.encode()) + if error: + raise VimbaException(error) + + def _get_string(self) -> str: + buffer_size = 256 + value = create_string_buffer('\x00' * buffer_size) + size_filled = c_uint32() + + error = vimba_c.vmb_feature_string_get(self._handle, + self._name, + value, + buffer_size, + byref(size_filled)) + if error: + raise VimbaException(error) + return value.value.decode() + + def _set_string(self, value: str) -> None: + error = vimba_c.vmb_feature_string_set(self._handle, + self._name, + value.encode()) + if error: + raise VimbaException(error) + + def _get_bool(self) -> bool: + value = c_bool() + error = vimba_c.vmb_feature_bool_get(self._handle, + self._name, + byref(value)) + if error: + raise VimbaException(error) + + return value.value + + def _set_bool(self, value: bool): + error = vimba_c.vmb_feature_bool_set(self._handle, + self._name, + value) + if error: + raise VimbaException(error) + + def _range_query_int(self) -> Tuple[int, int]: + range_min = c_int64() + range_max = c_int64() + error = vimba_c.vmb_feature_int_range_query(self._handle, + self._name, + byref(range_min), + byref(range_max)) + if error: + raise VimbaException(error) + + return int(range_min.value), int(range_max.value) + + def _range_query_float(self) -> Tuple[float, float]: + range_min = c_double() + range_max = c_double() + error = vimba_c.vmb_feature_float_range_query(self._handle, + self._name, + byref(range_min), + byref(range_max)) + if error: + raise VimbaException(error) + + return range_min.value, range_max.value + + def _range_query_enum(self) -> List[str]: + # call once to get number of available enum names + num_found = c_uint32(-1) + error = vimba_c.vmb_feature_enum_range_query(self._handle, + self._name, + None, + 0, + byref(num_found)) + if error: + raise VimbaException(error) + + # call again to get the actual enum names + num_enum_names = num_found.value + enum_names = (c_char_p * num_enum_names)() + error = vimba_c.vmb_feature_enum_range_query(self._handle, + self._name, + enum_names, + num_enum_names, + byref(num_found)) + if error: + raise VimbaException(error) + + return list(enum_name.decode() for enum_name in enum_names) diff --git a/pymba/frame.py b/pymba/frame.py new file mode 100644 index 0000000..1e01333 --- /dev/null +++ b/pymba/frame.py @@ -0,0 +1,175 @@ +from ctypes import byref, sizeof, addressof, create_string_buffer, cast, POINTER, c_ubyte, c_void_p +from typing import Optional +import warnings +try: + import numpy as np +except ImportError: + warnings.warn('could not import numpy, some Frame methods may not work.') + +from .camera import Camera +from .vimba_exception import VimbaException +from . import vimba_c + + +# Map pixel formats to bytes per pixel. +PIXEL_FORMATS = { + "Mono8": 1, + "Mono12": 2, + # untested + "Mono12Packed": 1.5, + "Mono14": 2, + "Mono16": 2, + "RGB8": 3, + "RGB8Packed": 3, + "BGR8Packed": 3, + "RGBA8Packed": 4, + "BGRA8Packed": 4, + # untested + "YUV411Packed": 4 / 3.0, + "YUV422Packed": 2, + "YUV444Packed": 3, + "BayerRG8": 1, + "BayerRG12": 2, + "BayerGR8": 1, + "BayerGR12": 2, + # untested + "BayerGR12Packed": 1.5, +} + + +class MemoryBlock: + """ + A memory block object for dealing neatly with C memory allocations. + """ + + @property + def block(self): + return c_void_p(addressof(self._block)) + + def __init__(self, block_size): + self._block = create_string_buffer(block_size) + + # this seems to be None if too much memory is requested + if self._block is None: + raise VimbaException(VimbaException.ERR_FRAME_BUFFER_MEMORY) + + def __del__(self): + del self._block + + +class Frame: + """ + A Vimba frame. + """ + + def __init__(self, camera: Camera): + self._camera = camera + self._handle = camera.handle + + # get frame sizes + self.payload_size = self._camera.PayloadSize + self.width = self._camera.Width + self.height = self._camera.Height + self.pixel_bytes = PIXEL_FORMATS[self._camera.PixelFormat] + + # frame structure + self._frame = vimba_c.VmbFrame() + + self._c_mem = None + + def announce(self): + """ + Announce frames to the API that may be queued for frame capturing later. Should be called after the frame is + created. Call startCapture after this method. + """ + # keep this reference to keep block alive for life of frame + self._c_mem = MemoryBlock(self.payload_size) + # set buffer to have length of expected payload size + self._frame.buffer = self._c_mem.block + + # set buffer size to expected payload size + self._frame.bufferSize = self.payload_size + + error = vimba_c.vmb_frame_announce(self._handle, + byref(self._frame), + sizeof(self._frame)) + if error: + raise VimbaException(error) + + def revoke(self): + """ + Revoke a frame from the API. + """ + error = vimba_c.vmb_frame_revoke(self._handle, + byref(self._frame)) + if error: + raise VimbaException(error) + + def queue_capture(self, frame_callback: Optional[bool] = None) -> None: + """ + Queue frames that may be filled during frame capturing. Call after announceFrame and startCapture. Callback + must accept argument of type frame. Remember to requeue the frame by calling frame.queue_capture() at the end + of your callback function. + """ + self._frame_callback = frame_callback + + # define a callback wrapper here so it doesn't bind self + def frame_callback_wrapper(cam_handle, p_frame): + # call the user's callback with the self bound outside the wrapper + # ignore the frame pointer since we already know the callback + # refers to this frame + self._frame_callback(self) + + if self._frame_callback is None: + self._frame_callback_wrapper_c = None + else: + # keep a reference to prevent gc issues + self._frame_callback_wrapper_c = vimba_c.vmb_frame_callback(frame_callback_wrapper) + + error = vimba_c.vmb_capture_frame_queue(self._handle, + byref(self._frame), + self._frame_callback_wrapper_c) + if error: + raise VimbaException(error) + + def wait_capture(self, timeout_ms: Optional[int] = 2000) -> int: + """ + Wait for a queued frame to be filled (or dequeued). Call after an acquisition command. + :param timeout_ms: time out in milliseconds. + """ + error = vimba_c.vmb_capture_frame_wait(self._handle, + byref(self._frame), + timeout_ms) + + # error to be processed by the end user for this function. + # Prevents system for breaking for example on a hardware trigger timeout + + # todo raise error instead? + + return error + + def get_buffer_data(self) -> c_ubyte * int: + """ + Retrieve buffer data in a useful format. + """ + # cast frame buffer memory contents to a usable type + data = cast(self._frame.buffer, POINTER(c_ubyte * self.payload_size)) + + # make array of c_ubytes from buffer + image_bytes = int(self.height * self.width * self.pixel_bytes) + return (c_ubyte * image_bytes).from_address(addressof(data.contents)) + + def get_image(self) -> np.ndarray: + """ + Returns the frame's image data as a NumPy array. + """ + data = cast(self._frame.buffer, POINTER(c_ubyte * self._frame.imageSize)) + return np.ndarray(buffer=data.contents, dtype=np.uint8, shape=(self._frame.height, self._frame.width)) + + @property + def timestamp(self) -> int: + return self._frame.timestamp + + @property + def receive_status(self) -> int: + return self._frame.receiveStatus diff --git a/pymba/interface.py b/pymba/interface.py new file mode 100644 index 0000000..a035b0a --- /dev/null +++ b/pymba/interface.py @@ -0,0 +1,37 @@ +from ctypes import byref + +from .vimba_object import VimbaObject +from .vimba_exception import VimbaException +from . import vimba_c + + +class Interface(VimbaObject): + """ + A Vimba interface object. This class provides the minimal access + to Vimba functions required to control the interface. + """ + + def __init__(self, id_string: str): + self._id_string = id_string.encode() + super().__init__() + + @property + def id_string(self): + return self._id_string.decode() + + def open(self): + """ + Open the interface. + """ + error = vimba_c.vmb_interface_open(self._id_string, + byref(self._handle)) + if error: + raise VimbaException(error) + + def close(self): + """ + Close the interface. + """ + error = vimba_c.vmb_interface_close(self._handle) + if error: + raise VimbaException(error) diff --git a/pymba/system.py b/pymba/system.py new file mode 100644 index 0000000..2cc6870 --- /dev/null +++ b/pymba/system.py @@ -0,0 +1,9 @@ +from .vimba_object import VimbaObject + + +class System(VimbaObject): + """ + A Vimba system object. This class provides the minimal access to Vimba functions required to control the system. + """ + def __init__(self): + super().__init__(handle=1) diff --git a/pymba/vimba.py b/pymba/vimba.py index 0d6c6b5..1174c3d 100644 --- a/pymba/vimba.py +++ b/pymba/vimba.py @@ -2,9 +2,9 @@ from ctypes import byref, sizeof, c_uint32 from typing import List from .vimba_exception import VimbaException -from .vimba_system import VimbaSystem -from .vimba_camera import VimbaCamera -from .vimba_interface import VimbaInterface +from .system import System +from .camera import Camera +from .interface import Interface from . import vimba_c @@ -17,7 +17,7 @@ class Vimba(object): def __init__(self): # create own system singleton object - self._system = VimbaSystem() + self._system = System() self._vmb_interface_infos = None self._interfaces = {} self._cameras = {} @@ -38,7 +38,7 @@ class Vimba(object): self.shutdown() @property - def system(self) -> VimbaSystem: + def system(self) -> System: """ Get the system object. """ @@ -172,7 +172,7 @@ class Vimba(object): raise VimbaException(error) return vmb_camera_info - def get_interface(self, id_string) -> VimbaInterface: + def get_interface(self, id_string) -> Interface: """ Gets interface object based on interface ID string. Will not recreate interface object if it already exists. :param id_string: the ID of the interface. @@ -181,11 +181,11 @@ class Vimba(object): if id_string in self.get_interface_ids(): # create it if it doesn't exist if id_string not in self._interfaces: - self._interfaces[id_string] = VimbaInterface(id_string) + self._interfaces[id_string] = Interface(id_string) return self._interfaces[id_string] raise VimbaException(VimbaException.ERR_INTERFACE_NOT_FOUND) - def get_camera(self, camera_id: str) -> VimbaCamera: + def get_camera(self, camera_id: str) -> Camera: """ Gets camera object based on camera ID string. Will not recreate camera object if it already exists. :param camera_id: the ID of the camera object to get. This can be an ID or e.g. a serial number. Check the Vimba @@ -195,7 +195,7 @@ class Vimba(object): if camera_id in self.get_camera_ids(): # create it if it doesn't exist if camera_id not in self._cameras: - self._cameras[camera_id] = VimbaCamera(camera_id) + self._cameras[camera_id] = Camera(camera_id) return self._cameras[camera_id] else: # the given string might not be a camera ID -> check for other IDs @@ -208,5 +208,5 @@ class Vimba(object): camera_id_string = vmb_camera_info.id_string.decode() if camera_id_string not in self._cameras: - self._cameras[camera_id_string] = VimbaCamera(camera_id_string) + self._cameras[camera_id_string] = Camera(camera_id_string) return self._cameras[camera_id_string] diff --git a/pymba/vimba_c.py b/pymba/vimba_c.py index ef547ae..b996720 100644 --- a/pymba/vimba_c.py +++ b/pymba/vimba_c.py @@ -3,8 +3,6 @@ import platform import os from ctypes import * -from .vimba_exception import VimbaException - if sys_plat == "win32": @@ -75,26 +73,6 @@ else: CALLBACK_FUNCTYPE = CFUNCTYPE -class MemoryBlock: - """ - A memory block object for dealing neatly with C memory allocations. - """ - - @property - def block(self): - return c_void_p(addressof(self._block)) - - def __init__(self, block_size): - self._block = create_string_buffer(block_size) - - # this seems to be None if too much memory is requested - if self._block is None: - raise VimbaException(VimbaException.ERR_FRAME_BUFFER_MEMORY) - - def __del__(self): - del self._block - - class VmbVersionInfo(Structure): _fields_ = [ ('major', c_uint32), diff --git a/pymba/vimba_camera.py b/pymba/vimba_camera.py deleted file mode 100644 index 27bd5d3..0000000 --- a/pymba/vimba_camera.py +++ /dev/null @@ -1,91 +0,0 @@ -from ctypes import byref, sizeof -from typing import Optional - -from .vimba_object import VimbaObject -from .vimba_exception import VimbaException -from .vimba_frame import VimbaFrame -from . import vimba_c - - -class VimbaCamera(VimbaObject): - """ - A Vimba camera object. - """ - - def __init__(self, id_string: str): - self._id_string = id_string.encode() - super().__init__() - self._info = self._get_info() - - @property - def id_string(self) -> str: - return self._id_string.decode() - - def _get_info(self) -> vimba_c.VmbCameraInfo: - """ - Get info of the camera. Does not require the camera to be opened. - """ - vmb_camera_info = vimba_c.VmbCameraInfo() - error = vimba_c.vmb_camera_info_query(self._id_string, - byref(vmb_camera_info), - sizeof(vmb_camera_info)) - if error: - raise VimbaException(error) - - return vmb_camera_info - - def open(self, camera_access_mode: Optional[int] = VimbaObject.VMB_ACCESS_MODE_FULL): - """ - Open the camera with requested access mode. - """ - error = vimba_c.vmb_camera_open(self._id_string, - camera_access_mode, - byref(self._handle)) - if error: - raise VimbaException(error) - - def close(self): - """ - Close the camera. - """ - error = vimba_c.vmb_camera_close(self._handle) - if error: - raise VimbaException(error) - - def revoke_all_frames(self): - """ - Revoke all frames assigned to the camera. - """ - error = vimba_c.vmb_frame_revoke_all(self._handle) - if error: - raise VimbaException(error) - - def start_capture(self): - """ - Prepare the API for incoming frames. - """ - error = vimba_c.vmb_capture_start(self._handle) - if error: - raise VimbaException(error) - - def end_capture(self): - """ - Stop the API from being able to receive frames. - """ - error = vimba_c.vmb_capture_end(self._handle) - if error: - raise VimbaException(error) - - def flush_capture_queue(self): - """ - Flush the capture queue. - """ - error = vimba_c.vmb_capture_queue_flush(self._handle) - if error: - raise VimbaException(error) - - def create_frame(self) -> VimbaFrame: - """ - Creates and returns a new frame object. Multiple frames per camera can therefore be returned. - """ - return VimbaFrame(self) diff --git a/pymba/vimba_feature.py b/pymba/vimba_feature.py deleted file mode 100644 index 6e68bea..0000000 --- a/pymba/vimba_feature.py +++ /dev/null @@ -1,225 +0,0 @@ -from ctypes import byref, sizeof, c_uint32, c_double, c_char_p, c_bool, c_int64, create_string_buffer -from typing import Tuple, List - -from .vimba_exception import VimbaException -from . import vimba_c - - -class VimbaFeature: - """ - A feature of a Vimba object. - """ - - ( - _FEATURE_DATA_UNKNOWN, - _FEATURE_DATA_INT, - _FEATURE_DATA_FLOAT, - _FEATURE_DATA_ENUM, - _FEATURE_DATA_STRING, - _FEATURE_DATA_BOOL, - _FEATURE_DATA_COMMAND, - _FEATURE_DATA_RAW, - _FEATURE_DATA_NONE, - ) = range(9) - - @property - def name(self): - return self._name.decode() - - @property - def handle(self): - return self._handle - - # lookup relevant function for feature type and pass to that function - @property - def value(self): - return self._feature_data_value_funcs[self._info.featureDataType][0]() - - @value.setter - def value(self, val): - self._feature_data_value_funcs[self._info.featureDataType][1](val) - - @property - def range(self): - return self._feature_data_range_funcs[self._info.featureDataType]() - - def __init__(self, name, handle): - self._name = name.encode() - self._handle = handle - - # type functions dict for looking up correct get/set function to use - self._feature_data_value_funcs = { - self._FEATURE_DATA_UNKNOWN: None, - self._FEATURE_DATA_INT: (self._get_int, self._set_int), - self._FEATURE_DATA_FLOAT: (self._get_float, self._set_float), - self._FEATURE_DATA_ENUM: (self._get_enum, self._set_enum), - self._FEATURE_DATA_STRING: (self._get_string, self._set_string), - self._FEATURE_DATA_BOOL: (self._get_bool, self._set_bool), - self._FEATURE_DATA_COMMAND: None, - self._FEATURE_DATA_RAW: None, - self._FEATURE_DATA_NONE: None, - } - - # type functions dict for looking up correct range function to use - self._feature_data_range_funcs = { - self._FEATURE_DATA_UNKNOWN: None, - self._FEATURE_DATA_INT: self._range_query_int, - self._FEATURE_DATA_FLOAT: self._range_query_float, - self._FEATURE_DATA_ENUM: self._range_query_enum, - self._FEATURE_DATA_STRING: None, - self._FEATURE_DATA_BOOL: None, - self._FEATURE_DATA_COMMAND: None, - self._FEATURE_DATA_RAW: None, - self._FEATURE_DATA_NONE: None, - } - - # get info once - self._info = self._get_info() - - def _get_info(self) -> vimba_c.VmbFeatureInfo: - vmb_feature_info = vimba_c.VmbFeatureInfo() - error = vimba_c.vmb_feature_info_query(self._handle, - self._name, - byref(vmb_feature_info), - sizeof(vmb_feature_info)) - if error: - raise VimbaException(error) - - return vmb_feature_info - - def _get_int(self) -> int: - value = c_int64() - error = vimba_c.vmb_feature_int_get(self._handle, - self._name, - byref(value)) - if error: - raise VimbaException(error) - - return value.value - - def _set_int(self, value: int) -> None: - error = vimba_c.vmb_feature_int_set(self._handle, - self._name, - value) - if error: - raise VimbaException(error) - - def _get_float(self) -> float: - value = c_double() - error = vimba_c.vmb_feature_float_get(self._handle, - self._name, - byref(value)) - if error: - raise VimbaException(error) - - return value.value - - def _set_float(self, value: float) -> None: - error = vimba_c.vmb_feature_float_set(self._handle, - self._name, - value) - if error: - raise VimbaException(error) - - def _get_enum(self) -> str: - value = c_char_p() - error = vimba_c.vmb_feature_enum_get(self._handle, - self._name, - byref(value)) - if error: - raise VimbaException(error) - - return value.value.decode() - - def _set_enum(self, value: str): - error = vimba_c.vmb_feature_enum_set(self._handle, - self._name, - value.encode()) - if error: - raise VimbaException(error) - - def _get_string(self) -> str: - buffer_size = 256 - value = create_string_buffer('\x00' * buffer_size) - size_filled = c_uint32() - - error = vimba_c.vmb_feature_string_get(self._handle, - self._name, - value, - buffer_size, - byref(size_filled)) - if error: - raise VimbaException(error) - return value.value.decode() - - def _set_string(self, value: str) -> None: - error = vimba_c.vmb_feature_string_set(self._handle, - self._name, - value.encode()) - if error: - raise VimbaException(error) - - def _get_bool(self) -> bool: - value = c_bool() - error = vimba_c.vmb_feature_bool_get(self._handle, - self._name, - byref(value)) - if error: - raise VimbaException(error) - - return value.value - - def _set_bool(self, value: bool): - error = vimba_c.vmb_feature_bool_set(self._handle, - self._name, - value) - if error: - raise VimbaException(error) - - def _range_query_int(self) -> Tuple[int, int]: - range_min = c_int64() - range_max = c_int64() - error = vimba_c.vmb_feature_int_range_query(self._handle, - self._name, - byref(range_min), - byref(range_max)) - if error: - raise VimbaException(error) - - return int(range_min.value), int(range_max.value) - - def _range_query_float(self) -> Tuple[float, float]: - range_min = c_double() - range_max = c_double() - error = vimba_c.vmb_feature_float_range_query(self._handle, - self._name, - byref(range_min), - byref(range_max)) - if error: - raise VimbaException(error) - - return range_min.value, range_max.value - - def _range_query_enum(self) -> List[str]: - # call once to get number of available enum names - num_found = c_uint32(-1) - error = vimba_c.vmb_feature_enum_range_query(self._handle, - self._name, - None, - 0, - byref(num_found)) - if error: - raise VimbaException(error) - - # call again to get the actual enum names - num_enum_names = num_found.value - enum_names = (c_char_p * num_enum_names)() - error = vimba_c.vmb_feature_enum_range_query(self._handle, - self._name, - enum_names, - num_enum_names, - byref(num_found)) - if error: - raise VimbaException(error) - - return list(enum_name.decode() for enum_name in enum_names) diff --git a/pymba/vimba_frame.py b/pymba/vimba_frame.py deleted file mode 100644 index 0832429..0000000 --- a/pymba/vimba_frame.py +++ /dev/null @@ -1,175 +0,0 @@ -from ctypes import byref, sizeof, addressof, create_string_buffer, cast, POINTER, c_ubyte, c_void_p -from typing import Optional -import warnings -try: - import numpy as np -except ImportError: - warnings.warn('could not import numpy, some Frame methods may not work.') - -from .vimba_camera import VimbaCamera -from .vimba_exception import VimbaException -from . import vimba_c - - -# Map pixel formats to bytes per pixel. -PIXEL_FORMATS = { - "Mono8": 1, - "Mono12": 2, - # untested - "Mono12Packed": 1.5, - "Mono14": 2, - "Mono16": 2, - "RGB8": 3, - "RGB8Packed": 3, - "BGR8Packed": 3, - "RGBA8Packed": 4, - "BGRA8Packed": 4, - # untested - "YUV411Packed": 4 / 3.0, - "YUV422Packed": 2, - "YUV444Packed": 3, - "BayerRG8": 1, - "BayerRG12": 2, - "BayerGR8": 1, - "BayerGR12": 2, - # untested - "BayerGR12Packed": 1.5, -} - - -class MemoryBlock: - """ - A memory block object for dealing neatly with C memory allocations. - """ - - @property - def block(self): - return c_void_p(addressof(self._block)) - - def __init__(self, block_size): - self._block = create_string_buffer(block_size) - - # this seems to be None if too much memory is requested - if self._block is None: - raise VimbaException(VimbaException.ERR_FRAME_BUFFER_MEMORY) - - def __del__(self): - del self._block - - -class Frame: - """ - A Vimba frame. - """ - - def __init__(self, camera: VimbaCamera): - self._camera = camera - self._handle = camera.handle - - # get frame sizes - self.payload_size = self._camera.PayloadSize - self.width = self._camera.Width - self.height = self._camera.Height - self.pixel_bytes = PIXEL_FORMATS[self._camera.PixelFormat] - - # frame structure - self._frame = vimba_c.VmbFrame() - - self._c_mem = None - - def announce(self): - """ - Announce frames to the API that may be queued for frame capturing later. Should be called after the frame is - created. Call startCapture after this method. - """ - # keep this reference to keep block alive for life of frame - self._c_mem = MemoryBlock(self.payload_size) - # set buffer to have length of expected payload size - self._frame.buffer = self._c_mem.block - - # set buffer size to expected payload size - self._frame.bufferSize = self.payload_size - - error = vimba_c.vmb_frame_announce(self._handle, - byref(self._frame), - sizeof(self._frame)) - if error: - raise VimbaException(error) - - def revoke(self): - """ - Revoke a frame from the API. - """ - error = vimba_c.vmb_frame_revoke(self._handle, - byref(self._frame)) - if error: - raise VimbaException(error) - - def queue_capture(self, frame_callback: Optional[bool] = None) -> None: - """ - Queue frames that may be filled during frame capturing. Call after announceFrame and startCapture. Callback - must accept argument of type frame. Remember to requeue the frame by calling frame.queue_capture() at the end - of your callback function. - """ - self._frame_callback = frame_callback - - # define a callback wrapper here so it doesn't bind self - def frame_callback_wrapper(cam_handle, p_frame): - # call the user's callback with the self bound outside the wrapper - # ignore the frame pointer since we already know the callback - # refers to this frame - self._frame_callback(self) - - if self._frame_callback is None: - self._frame_callback_wrapper_c = None - else: - # keep a reference to prevent gc issues - self._frame_callback_wrapper_c = vimba_c.vmb_frame_callback(frame_callback_wrapper) - - error = vimba_c.vmb_capture_frame_queue(self._handle, - byref(self._frame), - self._frame_callback_wrapper_c) - if error: - raise VimbaException(error) - - def wait_capture(self, timeout_ms: Optional[int] = 2000) -> int: - """ - Wait for a queued frame to be filled (or dequeued). Call after an acquisition command. - :param timeout_ms: time out in milliseconds. - """ - error = vimba_c.vmb_capture_frame_wait(self._handle, - byref(self._frame), - timeout_ms) - - # error to be processed by the end user for this function. - # Prevents system for breaking for example on a hardware trigger timeout - - # todo raise error instead? - - return error - - def get_buffer_data(self) -> c_ubyte * int: - """ - Retrieve buffer data in a useful format. - """ - # cast frame buffer memory contents to a usable type - data = cast(self._frame.buffer, POINTER(c_ubyte * self.payload_size)) - - # make array of c_ubytes from buffer - image_bytes = int(self.height * self.width * self.pixel_bytes) - return (c_ubyte * image_bytes).from_address(addressof(data.contents)) - - def get_image(self) -> np.ndarray: - """ - Returns the frame's image data as a NumPy array. - """ - data = cast(self._frame.buffer, POINTER(c_ubyte * self._frame.imageSize)) - return np.ndarray(buffer=data.contents, dtype=np.uint8, shape=(self._frame.height, self._frame.width)) - - @property - def timestamp(self) -> int: - return self._frame.timestamp - - @property - def receive_status(self) -> int: - return self._frame.receiveStatus diff --git a/pymba/vimba_interface.py b/pymba/vimba_interface.py deleted file mode 100644 index 647aa44..0000000 --- a/pymba/vimba_interface.py +++ /dev/null @@ -1,37 +0,0 @@ -from ctypes import byref - -from .vimba_object import VimbaObject -from .vimba_exception import VimbaException -from . import vimba_c - - -class VimbaInterface(VimbaObject): - """ - A Vimba interface object. This class provides the minimal access - to Vimba functions required to control the interface. - """ - - def __init__(self, id_string: str): - self._id_string = id_string.encode() - super().__init__() - - @property - def id_string(self): - return self._id_string.decode() - - def open(self): - """ - Open the interface. - """ - error = vimba_c.vmb_interface_open(self._id_string, - byref(self._handle)) - if error: - raise VimbaException(error) - - def close(self): - """ - Close the interface. - """ - error = vimba_c.vmb_interface_close(self._handle) - if error: - raise VimbaException(error) diff --git a/pymba/vimba_object.py b/pymba/vimba_object.py index 7199e61..f8d7c93 100644 --- a/pymba/vimba_object.py +++ b/pymba/vimba_object.py @@ -2,7 +2,7 @@ from ctypes import byref, sizeof, c_void_p, c_uint32, c_uint64, c_bool from typing import Union, Tuple, List, Optional from .vimba_exception import VimbaException -from .vimba_feature import VimbaFeature +from .feature import Feature from . import vimba_c @@ -35,7 +35,7 @@ class VimbaObject: def __getattr__(self, attr): # if a feature value requested (requires object (camera) open) if attr in self.get_feature_names(): - return VimbaFeature(attr, self._handle).value + return Feature(attr, self._handle).value # otherwise don't know about it raise AttributeError(''.join(["'VimbaObject' has no attribute '", attr, "'"])) @@ -51,7 +51,7 @@ class VimbaObject: # if it's an actual camera feature (requires camera open) elif attr in self.get_feature_names(): - VimbaFeature(attr, self._handle).value = val + Feature(attr, self._handle).value = val # otherwise just set the attribute value as normal else: @@ -125,7 +125,7 @@ class VimbaObject: list -- names of possible enum values (for enum features only). """ # shouldn't cache this - return VimbaFeature(feature_name, self._handle).range + return Feature(feature_name, self._handle).range def run_feature_command(self, feature_name: str) -> None: """ diff --git a/pymba/vimba_system.py b/pymba/vimba_system.py deleted file mode 100644 index 407bef6..0000000 --- a/pymba/vimba_system.py +++ /dev/null @@ -1,9 +0,0 @@ -from .vimba_object import VimbaObject - - -class VimbaSystem(VimbaObject): - """ - A Vimba system object. This class provides the minimal access to Vimba functions required to control the system. - """ - def __init__(self): - super().__init__(handle=1) -- cgit v1.2.3 From 86b277ea219240171a5befd8ac9a82765f56021d Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 23 Jan 2019 14:27:23 +1100 Subject: simple interface list example --- examples/list_cameras.py | 12 ------------ examples/show_cameras.py | 12 ++++++++++++ examples/show_interfaces.py | 7 +++++++ 3 files changed, 19 insertions(+), 12 deletions(-) delete mode 100644 examples/list_cameras.py create mode 100644 examples/show_cameras.py create mode 100644 examples/show_interfaces.py diff --git a/examples/list_cameras.py b/examples/list_cameras.py deleted file mode 100644 index 1d8258c..0000000 --- a/examples/list_cameras.py +++ /dev/null @@ -1,12 +0,0 @@ -from pymba.vimba import Vimba -from time import sleep - - -if __name__ == '__main__': - - with Vimba() as vmb: - # required for discovering GigE cameras - if vmb.system.GeVTLIsPresent: - vmb.system.run_feature_command("GeVDiscoveryAllOnce") - sleep(0.2) - print(vmb.camera_ids) diff --git a/examples/show_cameras.py b/examples/show_cameras.py new file mode 100644 index 0000000..39fffe8 --- /dev/null +++ b/examples/show_cameras.py @@ -0,0 +1,12 @@ +from pymba.vimba import Vimba +from time import sleep + + +if __name__ == '__main__': + + with Vimba() as vmb: + # required for discovering GigE cameras + if vmb.system.GeVTLIsPresent: + vmb.system.run_feature_command("GeVDiscoveryAllOnce") + sleep(0.2) + print(vmb.get_camera_ids()) diff --git a/examples/show_interfaces.py b/examples/show_interfaces.py new file mode 100644 index 0000000..9d95fc1 --- /dev/null +++ b/examples/show_interfaces.py @@ -0,0 +1,7 @@ +from pymba.vimba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vmb: + print(vmb.get_interface_ids()) -- cgit v1.2.3 From 12a2808655b8dfb1b1aa40605cb04dc2a59e3e85 Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 23 Jan 2019 14:28:38 +1100 Subject: system show example --- examples/show_system.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 examples/show_system.py diff --git a/examples/show_system.py b/examples/show_system.py new file mode 100644 index 0000000..4ce2807 --- /dev/null +++ b/examples/show_system.py @@ -0,0 +1,7 @@ +from pymba.vimba import Vimba + + +if __name__ == '__main__': + + vmb = Vimba() + print(vmb.system) -- cgit v1.2.3 From fc9eaae8105a1a4c1ad1a1a98397ba5c74a54983 Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 23 Jan 2019 14:29:16 +1100 Subject: untested auto refactor changes to tests --- tests/opencv_example.py | 32 ++++++++++++++++---------------- tests/opencv_liveview_example.py | 26 +++++++++++++------------- tests/opencv_liveview_example_color.py | 26 +++++++++++++------------- tests/test_cameras.py | 32 ++++++++++++++++---------------- tests/test_enumfeature.py | 2 +- tests/test_interfaces.py | 6 +++--- tests/test_systemfeature.py | 4 ++-- 7 files changed, 64 insertions(+), 64 deletions(-) diff --git a/tests/opencv_example.py b/tests/opencv_example.py index 238e8b4..edc6a5d 100644 --- a/tests/opencv_example.py +++ b/tests/opencv_example.py @@ -13,7 +13,7 @@ with Vimba() as vimba: # list available cameras (after enabling discovery for GigE cameras) if system.GeVTLIsPresent: - system.runFeatureCommand("GeVDiscoveryAllOnce") + system.run_feature_command("GeVDiscoveryAllOnce") time.sleep(0.2) cameraIds = vimba.getCameraIds() for cameraId in cameraIds: @@ -21,10 +21,10 @@ with Vimba() as vimba: # get and open a camera camera0 = vimba.getCamera(cameraIds[0]) - camera0.openCamera() + camera0.open() # list camera features - cameraFeatureNames = camera0.getFeatureNames() + cameraFeatureNames = camera0.get_feature_names() for name in cameraFeatureNames: print('Camera feature:', name) @@ -40,25 +40,25 @@ with Vimba() as vimba: camera0.AcquisitionMode = 'SingleFrame' # create new frames for the camera - frame0 = camera0.getFrame() # creates a frame - frame1 = camera0.getFrame() # creates a second frame + frame0 = camera0.create_frame() # creates a frame + frame1 = camera0.create_frame() # creates a second frame # announce frame - frame0.announceFrame() + frame0.announce() # capture a camera image count = 0 while count < 10: - camera0.startCapture() - frame0.queueFrameCapture() - camera0.runFeatureCommand('AcquisitionStart') - camera0.runFeatureCommand('AcquisitionStop') - frame0.waitFrameCapture() + camera0.start_capture() + frame0.queue_capture() + camera0.run_feature_command('AcquisitionStart') + camera0.run_feature_command('AcquisitionStop') + frame0.wait_capture() # get image data... - imgData = frame0.getBufferByteData() + imgData = frame0.get_buffer() - moreUsefulImgData = np.ndarray(buffer = frame0.getBufferByteData(), + moreUsefulImgData = np.ndarray(buffer = frame0.get_buffer(), dtype = np.uint8, shape = (frame0.height, frame0.width, @@ -67,10 +67,10 @@ with Vimba() as vimba: cv2.imwrite('foo{}.png'.format(count), rgb) print("image {} saved".format(count)) count += 1 - camera0.endCapture() + camera0.end_capture() # clean up after capture - camera0.revokeAllFrames() + camera0.revoke_all_frames() # close camera - camera0.closeCamera() + camera0.close() diff --git a/tests/opencv_liveview_example.py b/tests/opencv_liveview_example.py index 78b6b67..9c83264 100644 --- a/tests/opencv_liveview_example.py +++ b/tests/opencv_liveview_example.py @@ -16,7 +16,7 @@ cv2.namedWindow("test") with Vimba() as vimba: system = vimba.getSystem() - system.runFeatureCommand("GeVDiscoveryAllOnce") + system.run_feature_command("GeVDiscoveryAllOnce") time.sleep(0.2) camera_ids = vimba.getCameraIds() @@ -25,7 +25,7 @@ with Vimba() as vimba: print("Camera found: ", cam_id) c0 = vimba.getCamera(camera_ids[0]) - c0.openCamera() + c0.open() try: #gigE camera @@ -40,25 +40,25 @@ with Vimba() as vimba: c0.PixelFormat="Mono8" #c0.ExposureTimeAbs=60000 - frame = c0.getFrame() - frame.announceFrame() + frame = c0.create_frame() + frame.announce() - c0.startCapture() + c0.start_capture() framecount = 0 droppedframes = [] while 1: try: - frame.queueFrameCapture() + frame.queue_capture() success = True except: droppedframes.append(framecount) success = False - c0.runFeatureCommand("AcquisitionStart") - c0.runFeatureCommand("AcquisitionStop") - frame.waitFrameCapture(1000) - frame_data = frame.getBufferByteData() + c0.run_feature_command("AcquisitionStart") + c0.run_feature_command("AcquisitionStop") + frame.wait_capture(1000) + frame_data = frame.get_buffer() if success: img = np.ndarray(buffer=frame_data, dtype=np.uint8, @@ -73,7 +73,7 @@ with Vimba() as vimba: break - c0.endCapture() - c0.revokeAllFrames() + c0.end_capture() + c0.revoke_all_frames() - c0.closeCamera() + c0.close() diff --git a/tests/opencv_liveview_example_color.py b/tests/opencv_liveview_example_color.py index fd7a819..e2e2379 100644 --- a/tests/opencv_liveview_example_color.py +++ b/tests/opencv_liveview_example_color.py @@ -25,7 +25,7 @@ cv2.namedWindow("test") with Vimba() as vimba: system = vimba.getSystem() - system.runFeatureCommand("GeVDiscoveryAllOnce") + system.run_feature_command("GeVDiscoveryAllOnce") time.sleep(0.2) camera_ids = vimba.getCameraIds() @@ -34,7 +34,7 @@ with Vimba() as vimba: print("Camera found: ", cam_id) c0 = vimba.getCamera(camera_ids[0]) - c0.openCamera() + c0.open() try: #gigE camera @@ -49,25 +49,25 @@ with Vimba() as vimba: c0.PixelFormat = "BGR8Packed" # OPENCV DEFAULT time.sleep(0.2) - frame = c0.getFrame() - frame.announceFrame() + frame = c0.create_frame() + frame.announce() - c0.startCapture() + c0.start_capture() framecount = 0 droppedframes = [] while 1: try: - frame.queueFrameCapture() + frame.queue_capture() success = True except: droppedframes.append(framecount) success = False - c0.runFeatureCommand("AcquisitionStart") - c0.runFeatureCommand("AcquisitionStop") - frame.waitFrameCapture(1000) - frame_data = frame.getBufferByteData() + c0.run_feature_command("AcquisitionStart") + c0.run_feature_command("AcquisitionStop") + frame.wait_capture(1000) + frame_data = frame.get_buffer() if success: img = np.ndarray(buffer=frame_data, dtype=np.uint8, @@ -82,8 +82,8 @@ with Vimba() as vimba: break - c0.endCapture() - c0.revokeAllFrames() + c0.end_capture() + c0.revoke_all_frames() - c0.closeCamera() + c0.close() diff --git a/tests/test_cameras.py b/tests/test_cameras.py index a5a4dd9..7879ce8 100644 --- a/tests/test_cameras.py +++ b/tests/test_cameras.py @@ -12,7 +12,7 @@ def test_cameras(): # list available cameras (after enabling discovery for GigE cameras) if system.GeVTLIsPresent: - system.runFeatureCommand("GeVDiscoveryAllOnce") + system.run_feature_command("GeVDiscoveryAllOnce") time.sleep(0.2) cameraIds = vimba.getCameraIds() @@ -21,10 +21,10 @@ def test_cameras(): # get and open a camera camera0 = vimba.getCamera(cameraIds[0]) - camera0.openCamera() + camera0.open() # list camera features - cameraFeatureNames = camera0.getFeatureNames() + cameraFeatureNames = camera0.get_feature_names() for name in cameraFeatureNames: print('Camera feature:', name) @@ -35,37 +35,37 @@ def test_cameras(): camera0.AcquisitionMode = 'SingleFrame' # create new frames for the camera - frame0 = camera0.getFrame() # creates a frame - frame1 = camera0.getFrame() # creates a second frame + frame0 = camera0.create_frame() # creates a frame + frame1 = camera0.create_frame() # creates a second frame # announce frame - frame0.announceFrame() + frame0.announce() # capture a camera image - camera0.startCapture() - frame0.queueFrameCapture() - camera0.runFeatureCommand('AcquisitionStart') - camera0.runFeatureCommand('AcquisitionStop') - frame0.waitFrameCapture() + camera0.start_capture() + frame0.queue_capture() + camera0.run_feature_command('AcquisitionStart') + camera0.run_feature_command('AcquisitionStop') + frame0.wait_capture() # get image data... - imgData = frame0.getBufferByteData() + imgData = frame0.get_buffer() # ...or use NumPy for fast image display (for use with OpenCV, etc) import numpy as np - moreUsefulImgData = np.ndarray(buffer=frame0.getBufferByteData(), + moreUsefulImgData = np.ndarray(buffer=frame0.get_buffer(), dtype=np.uint8, shape=(frame0.height, frame0.width, 1)) # clean up after capture - camera0.endCapture() - camera0.revokeAllFrames() + camera0.end_capture() + camera0.revoke_all_frames() # close camera - camera0.closeCamera() + camera0.close() if __name__ == '__main__': diff --git a/tests/test_enumfeature.py b/tests/test_enumfeature.py index 7f9dd4c..0744820 100644 --- a/tests/test_enumfeature.py +++ b/tests/test_enumfeature.py @@ -12,7 +12,7 @@ def test_enumfeature(): print ("get enum value (DiscoveryCameraEvent): '%s'" % (system.DiscoveryCameraEvent)) # get enum range - range = system.getFeatureRange('DiscoveryCameraEvent') + range = system.get_feature_range('DiscoveryCameraEvent') print ("get enum value range (DiscoveryCameraEvent): '%s'" % (str(range))) # set enum value diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py index 270d42c..3fc4a94 100644 --- a/tests/test_interfaces.py +++ b/tests/test_interfaces.py @@ -14,15 +14,15 @@ def test_interfaces(): # get interface object and open it interface0 = vimba.getInterface(interfaceIds[0]) - interface0.openInterface() + interface0.open() # list interface features - interfaceFeatureNames = interface0.getFeatureNames() + interfaceFeatureNames = interface0.get_feature_names() for name in interfaceFeatureNames: print('Interface feature:', name) # close interface - interface0.closeInterface() + interface0.close() if __name__ == '__main__': test_interfaces() \ No newline at end of file diff --git a/tests/test_systemfeature.py b/tests/test_systemfeature.py index abb4da7..f61d55d 100644 --- a/tests/test_systemfeature.py +++ b/tests/test_systemfeature.py @@ -9,9 +9,9 @@ def test_systemfeature(): system = vimba.getSystem() # list system features - for featureName in system.getFeatureNames(): + for featureName in system.get_feature_names(): print('System feature:', featureName) - fInfo = system.getFeatureInfo(featureName) + fInfo = system.get_feature_info(featureName) for field in fInfo.getFieldNames(): print("\t", featureName, ":", field, getattr(fInfo, field)) -- cgit v1.2.3 From 76c040e9da5d94dfcb68d3e9a8003b894c1cf1dc Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 23 Jan 2019 16:23:26 +1100 Subject: test file for vimba.py --- tests/test_vimba.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/test_vimba.py diff --git a/tests/test_vimba.py b/tests/test_vimba.py new file mode 100644 index 0000000..4da713b --- /dev/null +++ b/tests/test_vimba.py @@ -0,0 +1,44 @@ +import pytest + +from pymba import Vimba, VimbaException + + +def test_version(): + version = Vimba().version.split('.') + assert int(version[0]) >= 1 + assert int(version[1]) >= 7 + assert int(version[2]) >= 0 + + +def test_startup_shutdown(): + with pytest.raises(VimbaException) as e: + Vimba().system().feature_names() + assert e.value.error_code == VimbaException.ERR_STARTUP_NOT_CALLED + + # manual + Vimba().startup() + Vimba().system().feature_names() + Vimba().shutdown() + + # context manager + with Vimba() as vmb: + vmb.system().feature_names() + + +@pytest.fixture +def vmb() -> Vimba: + with Vimba() as v: + yield v + + +# works best with camera(s) attached +def test_interface_camera_ids(vmb: Vimba): + # for ethernet camera discovery + if vmb.system().GeVTLIsPresent: + vmb.system().run_feature_command("GeVDiscoveryAllOnce") + + for func in (vmb.interface_ids, vmb.camera_ids): + ids = func() + assert isinstance(ids, list) + for x in ids: + assert isinstance(x, str) -- cgit v1.2.3 From ec2fee1b5b5a316314cd5c56cb3462236a1ec98a Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 23 Jan 2019 16:25:28 +1100 Subject: comments in code --- tests/test_vimba.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_vimba.py b/tests/test_vimba.py index 4da713b..5b1486e 100644 --- a/tests/test_vimba.py +++ b/tests/test_vimba.py @@ -37,6 +37,7 @@ def test_interface_camera_ids(vmb: Vimba): if vmb.system().GeVTLIsPresent: vmb.system().run_feature_command("GeVDiscoveryAllOnce") + # test id funcs return a list of strings (not bytes) for func in (vmb.interface_ids, vmb.camera_ids): ids = func() assert isinstance(ids, list) -- cgit v1.2.3 From da7d0e2d3f6881e768accfe9978892739dd7edd6 Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 23 Jan 2019 16:33:06 +1100 Subject: basic test for camera and interface --- tests/test_vimba.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/test_vimba.py b/tests/test_vimba.py index 5b1486e..27b3112 100644 --- a/tests/test_vimba.py +++ b/tests/test_vimba.py @@ -27,19 +27,26 @@ def test_startup_shutdown(): @pytest.fixture def vmb() -> Vimba: - with Vimba() as v: - yield v + with Vimba() as vmb: + # for ethernet camera discovery + if vmb.system().GeVTLIsPresent: + vmb.system().run_feature_command("GeVDiscoveryAllOnce") + yield vmb -# works best with camera(s) attached def test_interface_camera_ids(vmb: Vimba): - # for ethernet camera discovery - if vmb.system().GeVTLIsPresent: - vmb.system().run_feature_command("GeVDiscoveryAllOnce") - # test id funcs return a list of strings (not bytes) for func in (vmb.interface_ids, vmb.camera_ids): ids = func() assert isinstance(ids, list) + assert ids for x in ids: assert isinstance(x, str) + + +def test_interface(vmb: Vimba): + interface = vmb.interface(vmb.interface_ids()[0]) + + +def test_camera(vmb: Vimba): + camera = vmb.camera(vmb.camera_ids()[0]) -- cgit v1.2.3 From 38eb0149bcf922c4344b4d296f360cb6e95c8286 Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 23 Jan 2019 17:35:50 +1100 Subject: simplify import --- pymba/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pymba/__init__.py b/pymba/__init__.py index 7ade159..3325709 100644 --- a/pymba/__init__.py +++ b/pymba/__init__.py @@ -1,2 +1 @@ -from .vimba import Vimba -from .vimba_exception import VimbaException +from .vimba import Vimba, VimbaException -- cgit v1.2.3 From 5187175c5fe668659e9b35d527e2ddd1d9d9a725 Mon Sep 17 00:00:00 2001 From: morefigs Date: Fri, 25 Jan 2019 13:33:15 +1100 Subject: fixed type hints and circular import --- pymba/frame.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/pymba/frame.py b/pymba/frame.py index 1e01333..e3f698b 100644 --- a/pymba/frame.py +++ b/pymba/frame.py @@ -1,17 +1,16 @@ from ctypes import byref, sizeof, addressof, create_string_buffer, cast, POINTER, c_ubyte, c_void_p -from typing import Optional +from typing import Optional, Callable import warnings try: import numpy as np except ImportError: warnings.warn('could not import numpy, some Frame methods may not work.') -from .camera import Camera from .vimba_exception import VimbaException from . import vimba_c -# Map pixel formats to bytes per pixel. +# Map pixel formats to bytes per pixel PIXEL_FORMATS = { "Mono8": 1, "Mono12": 2, @@ -62,7 +61,7 @@ class Frame: A Vimba frame. """ - def __init__(self, camera: Camera): + def __init__(self, camera: 'Camera'): self._camera = camera self._handle = camera.handle @@ -105,7 +104,7 @@ class Frame: if error: raise VimbaException(error) - def queue_capture(self, frame_callback: Optional[bool] = None) -> None: + def queue_capture(self, frame_callback: Optional[Callable] = None) -> None: """ Queue frames that may be filled during frame capturing. Call after announceFrame and startCapture. Callback must accept argument of type frame. Remember to requeue the frame by calling frame.queue_capture() at the end @@ -114,17 +113,16 @@ class Frame: self._frame_callback = frame_callback # define a callback wrapper here so it doesn't bind self - def frame_callback_wrapper(cam_handle, p_frame): + def frame_callback_wrapper(camera_handle, frame_ptr): # call the user's callback with the self bound outside the wrapper - # ignore the frame pointer since we already know the callback - # refers to this frame + # ignore the frame pointer since we already know the callback refers to this frame self._frame_callback(self) if self._frame_callback is None: self._frame_callback_wrapper_c = None else: # keep a reference to prevent gc issues - self._frame_callback_wrapper_c = vimba_c.vmb_frame_callback(frame_callback_wrapper) + self._frame_callback_wrapper_c = vimba_c.vmb_frame_callback_func(frame_callback_wrapper) error = vimba_c.vmb_capture_frame_queue(self._handle, byref(self._frame), @@ -148,10 +146,13 @@ class Frame: return error - def get_buffer_data(self) -> c_ubyte * int: + def get_buffer_data(self): """ Retrieve buffer data in a useful format. """ + + # todo simplify? + # cast frame buffer memory contents to a usable type data = cast(self._frame.buffer, POINTER(c_ubyte * self.payload_size)) @@ -159,7 +160,7 @@ class Frame: image_bytes = int(self.height * self.width * self.pixel_bytes) return (c_ubyte * image_bytes).from_address(addressof(data.contents)) - def get_image(self) -> np.ndarray: + def get_image(self): """ Returns the frame's image data as a NumPy array. """ -- cgit v1.2.3 From 888eb9d0f9bb10e41bb5e928a51162b0b4683104 Mon Sep 17 00:00:00 2001 From: morefigs Date: Sun, 27 Jan 2019 11:58:21 +1100 Subject: nice structure class with better repr --- pymba/vimba_c.py | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/pymba/vimba_c.py b/pymba/vimba_c.py index b996720..034df6e 100644 --- a/pymba/vimba_c.py +++ b/pymba/vimba_c.py @@ -73,14 +73,35 @@ else: CALLBACK_FUNCTYPE = CFUNCTYPE -class VmbVersionInfo(Structure): +class NiceStructure(Structure): + def __repr__(self): + field_names = (field[0] for field in self._fields_) + return f'{type(self).__name__}(' \ + f'{", ".join("=".join((field, str(getattr(self, field)))) for field in field_names)})' + + +class VmbVersionInfo(NiceStructure): _fields_ = [ ('major', c_uint32), ('minor', c_uint32), ('patch', c_uint32)] -class VmbCameraInfo(Structure): +class VmbInterfaceInfo(NiceStructure): + _fields_ = [ + # Unique identifier for each interface + ('interfaceIdString', c_char_p), + # Interface type, see VmbInterfaceType + ('interfaceType', c_uint32), + # Interface name, given by the transport layer + ('interfaceName', c_char_p), + # Serial number + ('serialString', c_char_p), + # Used access mode, see VmbAccessModeType + ('permittedAccess', c_uint32)] + + +class VmbCameraInfo(NiceStructure): _fields_ = [ # Unique identifier for each camera ('cameraIdString', c_char_p), @@ -96,7 +117,7 @@ class VmbCameraInfo(Structure): ('interfaceIdString', c_char_p)] -class VmbFeatureInfo(Structure): +class VmbFeatureInfo(NiceStructure): _fields_ = [ ('name', c_char_p), ('featureDataType', c_uint32), @@ -155,28 +176,14 @@ class VmbFrame(Structure): ('timestamp', c_uint64)] -class VmbInterfaceInfo(Structure): - _fields_ = [ - # Unique identifier for each interface - ('interfaceIdString', c_char_p), - # Interface type, see VmbInterfaceType - ('interfaceType', c_uint32), - # Interface name, given by the transport layer - ('interfaceName', c_char_p), - # Serial number - ('serialString', c_char_p), - # Used access mode, see VmbAccessModeType - ('permittedAccess', c_uint32)] - - _vimba_lib = dll_loader.LoadLibrary(vimbaC_path) # ----- The below function signatures are defined in VimbaC.h ----- # callback for frame queue -vmb_frame_callback = CALLBACK_FUNCTYPE(c_void_p, - c_void_p, - POINTER(VmbFrame)) +vmb_frame_callback_func = CALLBACK_FUNCTYPE(c_void_p, + c_void_p, + POINTER(VmbFrame)) vmb_version_query = _vimba_lib.VmbVersionQuery vmb_version_query.restype = c_int32 -- cgit v1.2.3 From f6afc7f17d8a7351f21852f5c1e0994b8eefe690 Mon Sep 17 00:00:00 2001 From: morefigs Date: Sun, 27 Jan 2019 13:22:15 +1100 Subject: update usage examples --- examples/check_version.py | 7 ------- examples/get_camera.py | 16 ++++++++++++++++ examples/get_camera_ids.py | 14 ++++++++++++++ examples/get_interface.py | 9 +++++++++ examples/get_interface_ids.py | 7 +++++++ examples/get_version.py | 7 +++++++ 6 files changed, 53 insertions(+), 7 deletions(-) delete mode 100644 examples/check_version.py create mode 100644 examples/get_camera.py create mode 100644 examples/get_camera_ids.py create mode 100644 examples/get_interface.py create mode 100644 examples/get_interface_ids.py create mode 100644 examples/get_version.py diff --git a/examples/check_version.py b/examples/check_version.py deleted file mode 100644 index de8449c..0000000 --- a/examples/check_version.py +++ /dev/null @@ -1,7 +0,0 @@ -from pymba.vimba import Vimba - - -if __name__ == '__main__': - - vmb = Vimba() - print(vmb.version) diff --git a/examples/get_camera.py b/examples/get_camera.py new file mode 100644 index 0000000..3821053 --- /dev/null +++ b/examples/get_camera.py @@ -0,0 +1,16 @@ +from pymba import Vimba +from time import sleep + + +if __name__ == '__main__': + + with Vimba() as vmb: + + # required for discovering GigE cameras + if vmb.system().GeVTLIsPresent: + vmb.system().run_feature_command("GeVDiscoveryAllOnce") + sleep(0.2) + + # provide camera index or id + camera = vmb.camera(0) + print(camera) diff --git a/examples/get_camera_ids.py b/examples/get_camera_ids.py new file mode 100644 index 0000000..5f3341f --- /dev/null +++ b/examples/get_camera_ids.py @@ -0,0 +1,14 @@ +from pymba import Vimba +from time import sleep + + +if __name__ == '__main__': + + with Vimba() as vmb: + + # required for discovering GigE cameras + if vmb.system().GeVTLIsPresent: + vmb.system().run_feature_command("GeVDiscoveryAllOnce") + sleep(0.2) + + print(vmb.camera_ids()) diff --git a/examples/get_interface.py b/examples/get_interface.py new file mode 100644 index 0000000..797ce85 --- /dev/null +++ b/examples/get_interface.py @@ -0,0 +1,9 @@ +from pymba import Vimba, VimbaException + + +if __name__ == '__main__': + + with Vimba() as vmb: + # provide interface index or id + interface = vmb.interface(0) + print(interface) diff --git a/examples/get_interface_ids.py b/examples/get_interface_ids.py new file mode 100644 index 0000000..e93e7f2 --- /dev/null +++ b/examples/get_interface_ids.py @@ -0,0 +1,7 @@ +from pymba import Vimba, VimbaException + + +if __name__ == '__main__': + + with Vimba() as vmb: + print(vmb.interface_ids()) diff --git a/examples/get_version.py b/examples/get_version.py new file mode 100644 index 0000000..c482b0b --- /dev/null +++ b/examples/get_version.py @@ -0,0 +1,7 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + vmb = Vimba() + print(vmb.version) -- cgit v1.2.3 From 8bea834e445cc503d9800eb7575cd04b7b88812e Mon Sep 17 00:00:00 2001 From: morefigs Date: Sun, 27 Jan 2019 13:26:46 +1100 Subject: added feature name examples --- examples/get_cameras_feature_names.py | 18 ++++++++++++++++++ examples/get_interface_feature_names.py | 11 +++++++++++ 2 files changed, 29 insertions(+) create mode 100644 examples/get_cameras_feature_names.py create mode 100644 examples/get_interface_feature_names.py diff --git a/examples/get_cameras_feature_names.py b/examples/get_cameras_feature_names.py new file mode 100644 index 0000000..8b752e9 --- /dev/null +++ b/examples/get_cameras_feature_names.py @@ -0,0 +1,18 @@ +from pymba import Vimba +from time import sleep + + +if __name__ == '__main__': + + with Vimba() as vmb: + + # required for discovering GigE cameras + if vmb.system().GeVTLIsPresent: + vmb.system().run_feature_command("GeVDiscoveryAllOnce") + sleep(0.2) + + camera = vmb.camera(0) + camera.open() + for feature_name in camera.feature_names(): + print(feature_name) + camera.close() diff --git a/examples/get_interface_feature_names.py b/examples/get_interface_feature_names.py new file mode 100644 index 0000000..83cf1a3 --- /dev/null +++ b/examples/get_interface_feature_names.py @@ -0,0 +1,11 @@ +from pymba import Vimba, VimbaException + + +if __name__ == '__main__': + + with Vimba() as vmb: + interface = vmb.interface(0) + interface.open() + for feature_name in interface.feature_names(): + print(feature_name) + interface.close() -- cgit v1.2.3 From de54bb6b3b656b8185e479be30c5a80acf7fd63f Mon Sep 17 00:00:00 2001 From: morefigs Date: Sun, 27 Jan 2019 13:28:47 +1100 Subject: added system object examples --- examples/get_system.py | 8 ++++++++ examples/get_system_feature_names.py | 9 +++++++++ 2 files changed, 17 insertions(+) create mode 100644 examples/get_system.py create mode 100644 examples/get_system_feature_names.py diff --git a/examples/get_system.py b/examples/get_system.py new file mode 100644 index 0000000..2be6a09 --- /dev/null +++ b/examples/get_system.py @@ -0,0 +1,8 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vmb: + system = vmb.system() + print(system) diff --git a/examples/get_system_feature_names.py b/examples/get_system_feature_names.py new file mode 100644 index 0000000..1d41db2 --- /dev/null +++ b/examples/get_system_feature_names.py @@ -0,0 +1,9 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vmb: + system = vmb.system() + for feature_name in system.feature_names(): + print(feature_name) -- cgit v1.2.3 From 5e4be4f0ef982c34d8ef4bab0081b2c3594381bc Mon Sep 17 00:00:00 2001 From: morefigs Date: Sun, 27 Jan 2019 13:40:03 +1100 Subject: move general funcs to camera class --- pymba/camera.py | 76 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 17 deletions(-) diff --git a/pymba/camera.py b/pymba/camera.py index 16910fb..979371b 100644 --- a/pymba/camera.py +++ b/pymba/camera.py @@ -1,5 +1,5 @@ -from ctypes import byref, sizeof -from typing import Optional +from ctypes import byref, sizeof, c_uint32 +from typing import Optional, List from .vimba_object import VimbaObject from .vimba_exception import VimbaException @@ -7,38 +7,80 @@ from .frame import Frame from . import vimba_c +def _camera_infos() -> List[vimba_c.VmbCameraInfo]: + """ + Gets camera info of all attached cameras. + """ + # call once just to get the number of cameras + vmb_camera_info = vimba_c.VmbCameraInfo() + num_found = c_uint32(-1) + error = vimba_c.vmb_cameras_list(byref(vmb_camera_info), + 0, + byref(num_found), + sizeof(vmb_camera_info)) + if error and error != VimbaException.ERR_DATA_TOO_LARGE: + raise VimbaException(error) + + # call again to get the features + num_cameras = num_found.value + vmb_camera_infos = (vimba_c.VmbCameraInfo * num_cameras)() + error = vimba_c.vmb_cameras_list(vmb_camera_infos, + num_cameras, + byref(num_found), + sizeof(vmb_camera_info)) + if error: + raise VimbaException(error) + return list(vmb_camera_info for vmb_camera_info in vmb_camera_infos) + + +def _camera_info(id_string: str) -> vimba_c.VmbCameraInfo: + """ + Gets camera info object of specified camera. + :param cameraId: the ID of the camera object to get. This can be an ID or e.g. a serial number. Check the Vimba + documentation for other possible values. + """ + vmb_camera_info = vimba_c.VmbCameraInfo() + error = vimba_c.vmb_camera_info_query(id_string.encode(), + vmb_camera_info, + sizeof(vmb_camera_info)) + if error: + raise VimbaException(error) + return vmb_camera_info + + +def camera_ids(): + """ + Gets IDs of all available cameras. + """ + return list(vmb_camera_info.cameraIdString.decode() + for vmb_camera_info in _camera_infos()) + + class Camera(VimbaObject): """ A Vimba camera object. """ - def __init__(self, id_string: str): - self._id_string = id_string.encode() + def __init__(self, camera_id: str): + self._camera_id = camera_id super().__init__() - self._info = self._get_info() @property - def id_string(self) -> str: - return self._id_string.decode() + def camera_id(self) -> str: + return self._camera_id - def _get_info(self) -> vimba_c.VmbCameraInfo: + @property + def info(self) -> vimba_c.VmbCameraInfo: """ Get info of the camera. Does not require the camera to be opened. """ - vmb_camera_info = vimba_c.VmbCameraInfo() - error = vimba_c.vmb_camera_info_query(self._id_string, - byref(vmb_camera_info), - sizeof(vmb_camera_info)) - if error: - raise VimbaException(error) - - return vmb_camera_info + return _camera_info(self.camera_id) def open(self, camera_access_mode: Optional[int] = VimbaObject.VMB_ACCESS_MODE_FULL): """ Open the camera with requested access mode. """ - error = vimba_c.vmb_camera_open(self._id_string, + error = vimba_c.vmb_camera_open(self.camera_id.encode(), camera_access_mode, byref(self._handle)) if error: -- cgit v1.2.3 From 9b2c7bc2150a5945b06888cd24438fdb6fddbfb1 Mon Sep 17 00:00:00 2001 From: morefigs Date: Sun, 27 Jan 2019 13:40:31 +1100 Subject: move general funcs to interface module --- pymba/interface.py | 67 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/pymba/interface.py b/pymba/interface.py index a035b0a..fdd4675 100644 --- a/pymba/interface.py +++ b/pymba/interface.py @@ -1,29 +1,84 @@ -from ctypes import byref +from ctypes import byref, sizeof, c_uint32 +from typing import List from .vimba_object import VimbaObject from .vimba_exception import VimbaException from . import vimba_c +def _interface_infos() -> List[vimba_c.VmbInterfaceInfo]: + """ + Gets interface info of all available interfaces. + """ + # call once just to get the number of interfaces + num_found = c_uint32(-1) + error = vimba_c.vmb_interfaces_list(None, + 0, + byref(num_found), + sizeof(vimba_c.VmbInterfaceInfo)) + if error: + raise VimbaException(error) + + # call again to get the features + num_interfaces = num_found.value + vmb_interface_infos = (vimba_c.VmbInterfaceInfo * num_interfaces)() + error = vimba_c.vmb_interfaces_list(vmb_interface_infos, + num_interfaces, + byref(num_found), + sizeof(vimba_c.VmbInterfaceInfo)) + if error: + raise VimbaException(error) + + return list(vmb_interface_info for vmb_interface_info in vmb_interface_infos) + + +def _interface_info(interface_id: str) -> vimba_c.VmbInterfaceInfo: + """ + Gets interface info object of specified interface. + :param interface_id: the ID of the interface object to get. + """ + for vmb_interface_info in _interface_infos(): + if interface_id == vmb_interface_info.interfaceIdString.decode(): + return vmb_interface_info + raise VimbaException(VimbaException.ERR_INSTANCE_NOT_FOUND) + + +def interface_ids() -> List[str]: + """ + Gets IDs of all available interfaces. + """ + return list(vmb_interface_info.interfaceIdString.decode() + for vmb_interface_info in _interface_infos()) + + class Interface(VimbaObject): """ A Vimba interface object. This class provides the minimal access to Vimba functions required to control the interface. """ - def __init__(self, id_string: str): - self._id_string = id_string.encode() + def __init__(self, interface_id: str): + if interface_id not in interface_ids(): + raise VimbaException(VimbaException.ERR_INSTANCE_NOT_FOUND) + self._interface_id = interface_id super().__init__() @property - def id_string(self): - return self._id_string.decode() + def interface_id(self): + return self._interface_id + + @property + def info(self) -> vimba_c.VmbInterfaceInfo: + """ + Get info of the interface. Does not require the interface to be opened. + """ + return _interface_info(self.interface_id) def open(self): """ Open the interface. """ - error = vimba_c.vmb_interface_open(self._id_string, + error = vimba_c.vmb_interface_open(self.interface_id.encode(), byref(self._handle)) if error: raise VimbaException(error) -- cgit v1.2.3 From f2477b9f6a19fd21df6955e4818cf1274ce34a65 Mon Sep 17 00:00:00 2001 From: morefigs Date: Sun, 27 Jan 2019 13:43:42 +1100 Subject: refactor out camera and interface funcs --- pymba/vimba.py | 180 +++++++++++++-------------------------------------------- 1 file changed, 40 insertions(+), 140 deletions(-) diff --git a/pymba/vimba.py b/pymba/vimba.py index 1174c3d..a943083 100644 --- a/pymba/vimba.py +++ b/pymba/vimba.py @@ -1,14 +1,14 @@ -from ctypes import byref, sizeof, c_uint32 -from typing import List +from ctypes import sizeof +from typing import List, Union from .vimba_exception import VimbaException from .system import System -from .camera import Camera -from .interface import Interface +from .interface import Interface, interface_ids +from .camera import Camera, camera_ids from . import vimba_c -class Vimba(object): +class Vimba: """ Python wrapper for Allied Vision's Vimba C API. """ @@ -18,7 +18,6 @@ class Vimba(object): def __init__(self): # create own system singleton object self._system = System() - self._vmb_interface_infos = None self._interfaces = {} self._cameras = {} @@ -37,13 +36,6 @@ class Vimba(object): """ self.shutdown() - @property - def system(self) -> System: - """ - Get the system object. - """ - return self._system - @property def version(self) -> str: """ @@ -58,7 +50,8 @@ class Vimba(object): vmb_version_info.minor, vmb_version_info.patch)) - def startup(self): + @staticmethod + def startup(): """ Initialize the Vimba C API. """ @@ -66,147 +59,54 @@ class Vimba(object): if error: raise VimbaException(error) - def shutdown(self): + @staticmethod + def shutdown(): """ Perform a shutdown on the API. """ vimba_c.vmb_shutdown() - def _get_interface_infos(self) -> List[vimba_c.VmbInterfaceInfo]: - """ - Gets interface info of all available interfaces. - """ - - # todo is this caching required/harmful? - - if self._vmb_interface_infos is None: - num_found = c_uint32(-1) - - # call once just to get the number of interfaces - error = vimba_c.vmb_interfaces_list(None, - 0, - byref(num_found), - sizeof(vimba_c.VmbInterfaceInfo)) - if error: - raise VimbaException(error) - - # call again to get the features - num_interfaces = num_found.value - vmb_interface_infos = (vimba_c.VmbInterfaceInfo * num_interfaces)() - error = vimba_c.vmb_interfaces_list(vmb_interface_infos, - num_interfaces, - byref(num_found), - sizeof(vimba_c.VmbInterfaceInfo)) - if error: - raise VimbaException(error) - - self._vmb_interface_infos = list(vmb_interface_info for vmb_interface_info in vmb_interface_infos) - - return self._vmb_interface_infos - - def _get_camera_infos(self) -> List[vimba_c.VmbCameraInfo]: - """ - Gets camera info of all attached cameras. - """ - vmb_camera_info = vimba_c.VmbCameraInfo() - num_found = c_uint32(-1) - - # call once just to get the number of cameras - error = vimba_c.vmb_cameras_list(byref(vmb_camera_info), - 0, - byref(num_found), - sizeof(vmb_camera_info)) - if error and error != -9: - raise VimbaException(error) - - num_cameras = num_found.value - - # call again to get the features - vmb_camera_infos = (vimba_c.VmbCameraInfo * num_cameras)() - error = vimba_c.vmb_cameras_list(vmb_camera_infos, - num_cameras, - byref(num_found), - sizeof(vmb_camera_info)) - if error: - raise VimbaException(error) - return list(vmb_camera_info for vmb_camera_info in vmb_camera_infos) - - def get_interface_ids(self) -> List[str]: + def system(self) -> System: """ - Gets IDs of all available interfaces. + Get the system object. """ - return list(vmb_interface_info.id_string for vmb_interface_info in self._get_interface_infos()) + return self._system - def get_camera_ids(self) -> List[str]: - """ - Gets IDs of all available cameras. - """ - return list(camera_info.id_string.decode() for camera_info in self._get_camera_infos()) + @staticmethod + def interface_ids(): + return interface_ids() - def _get_interface_info(self, id_string: str) -> vimba_c.VmbInterfaceInfo: + def interface(self, interface_id: Union[str, int]) -> Interface: """ - Gets interface info object of specified interface. - :param id_string: the ID of the interface object to get. + Gets interface object based on interface ID string or index. Will not recreate interface object if it already exists. + :param interface_id: the ID or the index of the interface. """ - # don't do this live as we already have this info - # return info object if it exists - for vmb_interface_info in self._get_interface_infos(): + # if index is provided, look up the camera id using the index + if isinstance(interface_id, int): + interface_id = interface_ids()[interface_id] - # todo broken lookup on info objects + if interface_id in self._interfaces: + return self._interfaces[interface_id] + interface = Interface(interface_id) + self._interfaces[interface_id] = interface + return interface - if vmb_interface_info.id_string == id_string: - return vmb_interface_info - raise VimbaException(VimbaException.ERR_INTERFACE_NOT_FOUND) + @staticmethod + def camera_ids() -> List[str]: + return camera_ids() - def _get_camera_info(self, id_string: str) -> vimba_c.VmbCameraInfo: + def camera(self, camera_id: Union[str, int]) -> Camera: """ - Gets camera info object of specified camera. - :param cameraId: the ID of the camera object to get. This can be an ID or e.g. a serial number. Check the Vimba - documentation for other possible values. + Gets camera object based on camera ID string or index. Will not recreate camera object if it already exists. + :param camera_id: the ID or the index of the camera object to get. This can be an ID or e.g. a serial number. + Check the Vimba documentation for other possible values. """ - vmb_camera_info = vimba_c.VmbCameraInfo() - error = vimba_c.vmb_camera_info_query(id_string.encode(), - vmb_camera_info, - sizeof(vmb_camera_info)) - if error: - raise VimbaException(error) - return vmb_camera_info + # if index is provided, look up the camera id using the index + if isinstance(camera_id, int): + camera_id = camera_ids()[camera_id] - def get_interface(self, id_string) -> Interface: - """ - Gets interface object based on interface ID string. Will not recreate interface object if it already exists. - :param id_string: the ID of the interface. - """ - # check ID is valid - if id_string in self.get_interface_ids(): - # create it if it doesn't exist - if id_string not in self._interfaces: - self._interfaces[id_string] = Interface(id_string) - return self._interfaces[id_string] - raise VimbaException(VimbaException.ERR_INTERFACE_NOT_FOUND) - - def get_camera(self, camera_id: str) -> Camera: - """ - Gets camera object based on camera ID string. Will not recreate camera object if it already exists. - :param camera_id: the ID of the camera object to get. This can be an ID or e.g. a serial number. Check the Vimba - documentation for other possible values. - """ - # check ID is valid - if camera_id in self.get_camera_ids(): - # create it if it doesn't exist - if camera_id not in self._cameras: - self._cameras[camera_id] = Camera(camera_id) + if camera_id in self._cameras: return self._cameras[camera_id] - else: - # the given string might not be a camera ID -> check for other IDs - vmb_camera_info = vimba_c.VmbCameraInfo() - error = vimba_c.vmb_camera_info_query(camera_id.encode(), - vmb_camera_info, - sizeof(vmb_camera_info)) - if error: - raise VimbaException(error) - - camera_id_string = vmb_camera_info.id_string.decode() - if camera_id_string not in self._cameras: - self._cameras[camera_id_string] = Camera(camera_id_string) - return self._cameras[camera_id_string] + camera = Camera(camera_id) + self._cameras[camera_id] = camera + return camera -- cgit v1.2.3 From c63ba37c7f8da03de4fd8030bd392b966be7f335 Mon Sep 17 00:00:00 2001 From: morefigs Date: Sun, 27 Jan 2019 13:45:27 +1100 Subject: delete old examples --- examples/show_cameras.py | 12 ------------ examples/show_interfaces.py | 7 ------- examples/show_system.py | 7 ------- 3 files changed, 26 deletions(-) delete mode 100644 examples/show_cameras.py delete mode 100644 examples/show_interfaces.py delete mode 100644 examples/show_system.py diff --git a/examples/show_cameras.py b/examples/show_cameras.py deleted file mode 100644 index 39fffe8..0000000 --- a/examples/show_cameras.py +++ /dev/null @@ -1,12 +0,0 @@ -from pymba.vimba import Vimba -from time import sleep - - -if __name__ == '__main__': - - with Vimba() as vmb: - # required for discovering GigE cameras - if vmb.system.GeVTLIsPresent: - vmb.system.run_feature_command("GeVDiscoveryAllOnce") - sleep(0.2) - print(vmb.get_camera_ids()) diff --git a/examples/show_interfaces.py b/examples/show_interfaces.py deleted file mode 100644 index 9d95fc1..0000000 --- a/examples/show_interfaces.py +++ /dev/null @@ -1,7 +0,0 @@ -from pymba.vimba import Vimba - - -if __name__ == '__main__': - - with Vimba() as vmb: - print(vmb.get_interface_ids()) diff --git a/examples/show_system.py b/examples/show_system.py deleted file mode 100644 index 4ce2807..0000000 --- a/examples/show_system.py +++ /dev/null @@ -1,7 +0,0 @@ -from pymba.vimba import Vimba - - -if __name__ == '__main__': - - vmb = Vimba() - print(vmb.system) -- cgit v1.2.3 From 9a82feee9e10810c10750d3e4c4ecba58b2749d0 Mon Sep 17 00:00:00 2001 From: morefigs Date: Sun, 27 Jan 2019 14:19:11 +1100 Subject: added Pymba version --- pymba/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pymba/__init__.py b/pymba/__init__.py index 3325709..b067302 100644 --- a/pymba/__init__.py +++ b/pymba/__init__.py @@ -1 +1,4 @@ from .vimba import Vimba, VimbaException + + +PYMBA_VERSION = 0.2 -- cgit v1.2.3 From 8f6ac20bf8e090cca1ce537f27079bcd5b3dea46 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 29 Jan 2019 10:02:43 +1100 Subject: show pymba version --- examples/get_version.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/get_version.py b/examples/get_version.py index c482b0b..e03fe12 100644 --- a/examples/get_version.py +++ b/examples/get_version.py @@ -1,7 +1,8 @@ -from pymba import Vimba +from pymba import Vimba, PYMBA_VERSION if __name__ == '__main__': + print(f'Pymba version: {PYMBA_VERSION}') vmb = Vimba() - print(vmb.version) + print(f'Vimba version: {vmb.version}') -- cgit v1.2.3 From e3d3291bea56a9c7185aad27ba4084c615f7e661 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 29 Jan 2019 10:18:21 +1100 Subject: clean up and add new examples --- examples/get_camera.py | 7 ------- examples/get_camera_feature_names.py | 13 +++++++++++++ examples/get_camera_ids.py | 7 ------- examples/get_cameras_feature_names.py | 18 ------------------ examples/get_interface.py | 2 +- examples/get_interface_feature_names.py | 4 +++- examples/get_interface_ids.py | 2 +- examples/get_system_feature_names.py | 9 --------- 8 files changed, 18 insertions(+), 44 deletions(-) create mode 100644 examples/get_camera_feature_names.py delete mode 100644 examples/get_cameras_feature_names.py delete mode 100644 examples/get_system_feature_names.py diff --git a/examples/get_camera.py b/examples/get_camera.py index 3821053..5a9285b 100644 --- a/examples/get_camera.py +++ b/examples/get_camera.py @@ -1,16 +1,9 @@ from pymba import Vimba -from time import sleep if __name__ == '__main__': with Vimba() as vmb: - - # required for discovering GigE cameras - if vmb.system().GeVTLIsPresent: - vmb.system().run_feature_command("GeVDiscoveryAllOnce") - sleep(0.2) - # provide camera index or id camera = vmb.camera(0) print(camera) diff --git a/examples/get_camera_feature_names.py b/examples/get_camera_feature_names.py new file mode 100644 index 0000000..fcf6a8a --- /dev/null +++ b/examples/get_camera_feature_names.py @@ -0,0 +1,13 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vmb: + camera = vmb.camera(0) + camera.open() + + for feature_name in camera.feature_names(): + print(feature_name) + + camera.close() diff --git a/examples/get_camera_ids.py b/examples/get_camera_ids.py index 5f3341f..fe37242 100644 --- a/examples/get_camera_ids.py +++ b/examples/get_camera_ids.py @@ -1,14 +1,7 @@ from pymba import Vimba -from time import sleep if __name__ == '__main__': with Vimba() as vmb: - - # required for discovering GigE cameras - if vmb.system().GeVTLIsPresent: - vmb.system().run_feature_command("GeVDiscoveryAllOnce") - sleep(0.2) - print(vmb.camera_ids()) diff --git a/examples/get_cameras_feature_names.py b/examples/get_cameras_feature_names.py deleted file mode 100644 index 8b752e9..0000000 --- a/examples/get_cameras_feature_names.py +++ /dev/null @@ -1,18 +0,0 @@ -from pymba import Vimba -from time import sleep - - -if __name__ == '__main__': - - with Vimba() as vmb: - - # required for discovering GigE cameras - if vmb.system().GeVTLIsPresent: - vmb.system().run_feature_command("GeVDiscoveryAllOnce") - sleep(0.2) - - camera = vmb.camera(0) - camera.open() - for feature_name in camera.feature_names(): - print(feature_name) - camera.close() diff --git a/examples/get_interface.py b/examples/get_interface.py index 797ce85..331f650 100644 --- a/examples/get_interface.py +++ b/examples/get_interface.py @@ -1,4 +1,4 @@ -from pymba import Vimba, VimbaException +from pymba import Vimba if __name__ == '__main__': diff --git a/examples/get_interface_feature_names.py b/examples/get_interface_feature_names.py index 83cf1a3..36bf7be 100644 --- a/examples/get_interface_feature_names.py +++ b/examples/get_interface_feature_names.py @@ -1,4 +1,4 @@ -from pymba import Vimba, VimbaException +from pymba import Vimba if __name__ == '__main__': @@ -6,6 +6,8 @@ if __name__ == '__main__': with Vimba() as vmb: interface = vmb.interface(0) interface.open() + for feature_name in interface.feature_names(): print(feature_name) + interface.close() diff --git a/examples/get_interface_ids.py b/examples/get_interface_ids.py index e93e7f2..92df889 100644 --- a/examples/get_interface_ids.py +++ b/examples/get_interface_ids.py @@ -1,4 +1,4 @@ -from pymba import Vimba, VimbaException +from pymba import Vimba if __name__ == '__main__': diff --git a/examples/get_system_feature_names.py b/examples/get_system_feature_names.py deleted file mode 100644 index 1d41db2..0000000 --- a/examples/get_system_feature_names.py +++ /dev/null @@ -1,9 +0,0 @@ -from pymba import Vimba - - -if __name__ == '__main__': - - with Vimba() as vmb: - system = vmb.system() - for feature_name in system.feature_names(): - print(feature_name) -- cgit v1.2.3 From ed8292a1427a422770c983bace843520b5da46a7 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 29 Jan 2019 10:18:43 +1100 Subject: added new usage examples --- examples/get_interface_feature_values.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 examples/get_interface_feature_values.py diff --git a/examples/get_interface_feature_values.py b/examples/get_interface_feature_values.py new file mode 100644 index 0000000..335b477 --- /dev/null +++ b/examples/get_interface_feature_values.py @@ -0,0 +1,27 @@ +from pymba import Vimba, VimbaException + + +if __name__ == '__main__': + + with Vimba() as vmb: + interface = vmb.interface(0) + interface.open() + + # get feature value via feature object + for feature_name in interface.feature_names(): + feature = interface.feature(feature_name) + + try: + value = feature.value + + # alternatively the feature value can be read as an object attribute + # value = getattr(interface, feature_name) + # or + # value = interface.someFeatureName + + except VimbaException as e: + value = e + + print(feature_name, '--', value) + + interface.close() -- cgit v1.2.3 From 220fd5201be8d1a149abcf1637ed8bcc04123dfe Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 29 Jan 2019 10:18:57 +1100 Subject: added new usage examples --- examples/get_camera_feature_infos.py | 14 ++++++++++++++ examples/get_camera_feature_values.py | 27 +++++++++++++++++++++++++++ examples/get_interface_feature_infos.py | 14 ++++++++++++++ examples/get_system_feature_values.py | 24 ++++++++++++++++++++++++ examples/set_camera_feature_value.py | 18 ++++++++++++++++++ examples/set_interface_feature_value.py | 19 +++++++++++++++++++ 6 files changed, 116 insertions(+) create mode 100644 examples/get_camera_feature_infos.py create mode 100644 examples/get_camera_feature_values.py create mode 100644 examples/get_interface_feature_infos.py create mode 100644 examples/get_system_feature_values.py create mode 100644 examples/set_camera_feature_value.py create mode 100644 examples/set_interface_feature_value.py diff --git a/examples/get_camera_feature_infos.py b/examples/get_camera_feature_infos.py new file mode 100644 index 0000000..78e2752 --- /dev/null +++ b/examples/get_camera_feature_infos.py @@ -0,0 +1,14 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vmb: + camera = vmb.camera(0) + camera.open() + + for feature_name in camera.feature_names(): + feature = camera.feature(feature_name) + print(feature.info) + + camera.close() diff --git a/examples/get_camera_feature_values.py b/examples/get_camera_feature_values.py new file mode 100644 index 0000000..89f1582 --- /dev/null +++ b/examples/get_camera_feature_values.py @@ -0,0 +1,27 @@ +from pymba import Vimba, VimbaException + + +if __name__ == '__main__': + + with Vimba() as vmb: + camera = vmb.camera(0) + camera.open() + + # get feature value via feature object + for feature_name in camera.feature_names(): + feature = camera.feature(feature_name) + + try: + value = feature.value + + # alternatively the feature value can be read as an object attribute + # value = getattr(camera, feature_name) + # or + # value = camera.someFeatureName + + except VimbaException as e: + value = e + + print(feature_name, '--', value) + + camera.close() diff --git a/examples/get_interface_feature_infos.py b/examples/get_interface_feature_infos.py new file mode 100644 index 0000000..8330a3d --- /dev/null +++ b/examples/get_interface_feature_infos.py @@ -0,0 +1,14 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vmb: + interface = vmb.interface(0) + interface.open() + + for feature_name in interface.feature_names(): + feature = interface.feature(feature_name) + print(feature.info) + + interface.close() diff --git a/examples/get_system_feature_values.py b/examples/get_system_feature_values.py new file mode 100644 index 0000000..c83f292 --- /dev/null +++ b/examples/get_system_feature_values.py @@ -0,0 +1,24 @@ +from pymba import Vimba, VimbaException + + +if __name__ == '__main__': + + with Vimba() as vmb: + system = vmb.system() + + # get feature value via feature object + for feature_name in system.feature_names(): + feature = system.feature(feature_name) + + try: + value = feature.value + + # alternatively the feature value can be read as an object attribute + # value = getattr(system, feature_name) + # or + # value = system.someFeatureName + + except VimbaException as e: + value = e + + print(feature_name, '--', value) diff --git a/examples/set_camera_feature_value.py b/examples/set_camera_feature_value.py new file mode 100644 index 0000000..a33bf88 --- /dev/null +++ b/examples/set_camera_feature_value.py @@ -0,0 +1,18 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vmb: + camera = vmb.camera(0) + camera.open() + + # set a feature value by feature name + feature = camera.feature('ExposureAuto') + print(feature.value) + feature.value = feature.value + + # alternatively the feature value can be set as an object attribute + camera.ExposureAuto = feature.value + + camera.close() diff --git a/examples/set_interface_feature_value.py b/examples/set_interface_feature_value.py new file mode 100644 index 0000000..0fc80a2 --- /dev/null +++ b/examples/set_interface_feature_value.py @@ -0,0 +1,19 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vmb: + interface = vmb.interface(0) + interface.open() + + # set a feature value by feature name + feature = interface.feature('InterfacePingPace') + print(feature.value) + feature.value = 3 + print(feature.value) + + # alternatively the feature value can be set as an object attribute + interface.InterfacePingPace = 3 + + interface.close() -- cgit v1.2.3 From 8ef8e190089502592dd68b064c401f25c85cae2e Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 29 Jan 2019 10:23:00 +1100 Subject: simplify feature data type func lookup --- pymba/feature.py | 99 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/pymba/feature.py b/pymba/feature.py index f81ea6a..7ac403d 100644 --- a/pymba/feature.py +++ b/pymba/feature.py @@ -1,82 +1,91 @@ from ctypes import byref, sizeof, c_uint32, c_double, c_char_p, c_bool, c_int64, create_string_buffer -from typing import Tuple, List +from typing import Tuple, List, Callable from .vimba_exception import VimbaException from . import vimba_c +( + _FEATURE_DATA_UNKNOWN, + _FEATURE_DATA_INT, + _FEATURE_DATA_FLOAT, + _FEATURE_DATA_ENUM, + _FEATURE_DATA_STRING, + _FEATURE_DATA_BOOL, + _FEATURE_DATA_COMMAND, + _FEATURE_DATA_RAW, + _FEATURE_DATA_NONE, +) = range(9) + + class Feature: """ A feature of a Vimba object. """ - ( - _FEATURE_DATA_UNKNOWN, - _FEATURE_DATA_INT, - _FEATURE_DATA_FLOAT, - _FEATURE_DATA_ENUM, - _FEATURE_DATA_STRING, - _FEATURE_DATA_BOOL, - _FEATURE_DATA_COMMAND, - _FEATURE_DATA_RAW, - _FEATURE_DATA_NONE, - ) = range(9) - @property def name(self): return self._name.decode() @property - def handle(self): - return self._handle + def info(self) -> vimba_c.VmbFeatureInfo: + return self._feature_info() - # lookup relevant function for feature type and pass to that function @property def value(self): - return self._feature_data_value_funcs[self._info.featureDataType][0]() + return self._access_func('get', self.info.featureDataType)() @value.setter def value(self, val): - self._feature_data_value_funcs[self._info.featureDataType][1](val) + self._access_func('set', self.info.featureDataType)(val) @property def range(self): - return self._feature_data_range_funcs[self._info.featureDataType]() + return self._access_func('range', self.info.featureDataType)() def __init__(self, name, handle): self._name = name.encode() self._handle = handle - # type functions dict for looking up correct get/set function to use - self._feature_data_value_funcs = { - self._FEATURE_DATA_UNKNOWN: None, - self._FEATURE_DATA_INT: (self._get_int, self._set_int), - self._FEATURE_DATA_FLOAT: (self._get_float, self._set_float), - self._FEATURE_DATA_ENUM: (self._get_enum, self._set_enum), - self._FEATURE_DATA_STRING: (self._get_string, self._set_string), - self._FEATURE_DATA_BOOL: (self._get_bool, self._set_bool), - self._FEATURE_DATA_COMMAND: None, - self._FEATURE_DATA_RAW: None, - self._FEATURE_DATA_NONE: None, + def _access_func(self, func_type: str, data_type: int) -> Callable: + """ + Get the correct function needed to access the feature attribute based on the feature's data type. + :param func_type: One of 'get', 'set', or 'range'. + :param data_type: Data type as defined in VmbFeatureDataType. + """ + # (getter, setter, range) funcs + access_funcs = { + _FEATURE_DATA_UNKNOWN: (), + _FEATURE_DATA_INT: (self._get_int, + self._set_int, + self._range_query_int), + _FEATURE_DATA_FLOAT: (self._get_float, + self._set_float, + self._range_query_float), + _FEATURE_DATA_ENUM: (self._get_enum, + self._set_enum, + self._range_query_enum), + _FEATURE_DATA_STRING: (self._get_string, + self._set_string), + _FEATURE_DATA_BOOL: (self._get_bool, + self._set_bool), + _FEATURE_DATA_COMMAND: (), + _FEATURE_DATA_RAW: (), + _FEATURE_DATA_NONE: (), } - # type functions dict for looking up correct range function to use - self._feature_data_range_funcs = { - self._FEATURE_DATA_UNKNOWN: None, - self._FEATURE_DATA_INT: self._range_query_int, - self._FEATURE_DATA_FLOAT: self._range_query_float, - self._FEATURE_DATA_ENUM: self._range_query_enum, - self._FEATURE_DATA_STRING: None, - self._FEATURE_DATA_BOOL: None, - self._FEATURE_DATA_COMMAND: None, - self._FEATURE_DATA_RAW: None, - self._FEATURE_DATA_NONE: None, + access_indices = { + 'get': 0, + 'set': 1, + 'range': 2, } - # get info once - self._info = self._get_info() + try: + return access_funcs[data_type][access_indices[func_type]] + except IndexError: + raise VimbaException(VimbaException.ERR_NOT_IMPLEMENTED_IN_PYMBA) - def _get_info(self) -> vimba_c.VmbFeatureInfo: + def _feature_info(self) -> vimba_c.VmbFeatureInfo: vmb_feature_info = vimba_c.VmbFeatureInfo() error = vimba_c.vmb_feature_info_query(self._handle, self._name, @@ -140,7 +149,7 @@ class Feature: def _get_string(self) -> str: buffer_size = 256 - value = create_string_buffer('\x00' * buffer_size) + value = create_string_buffer(buffer_size) size_filled = c_uint32() error = vimba_c.vmb_feature_string_get(self._handle, -- cgit v1.2.3 From 9ef9b70070678fe3d4663ca70cd1dec3094eac6a Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 29 Jan 2019 10:23:22 +1100 Subject: automatically check for GigE devices --- pymba/vimba.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pymba/vimba.py b/pymba/vimba.py index a943083..795e03f 100644 --- a/pymba/vimba.py +++ b/pymba/vimba.py @@ -50,8 +50,7 @@ class Vimba: vmb_version_info.minor, vmb_version_info.patch)) - @staticmethod - def startup(): + def startup(self): """ Initialize the Vimba C API. """ @@ -59,6 +58,10 @@ class Vimba: if error: raise VimbaException(error) + # automatically check for the presence of a GigE transport layer + if self.system().GeVTLIsPresent: + self.system().run_feature_command('GeVDiscoveryAllOnce') + @staticmethod def shutdown(): """ -- cgit v1.2.3 From 75e39ba4f1fbbed406a1d7de7b5d4fa52d3859f1 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 29 Jan 2019 10:24:25 +1100 Subject: remove unused custom errors --- pymba/vimba_exception.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/pymba/vimba_exception.py b/pymba/vimba_exception.py index 4ce9e93..22f03c2 100644 --- a/pymba/vimba_exception.py +++ b/pymba/vimba_exception.py @@ -1,4 +1,3 @@ - class VimbaException(Exception): ERROR_CODES = ( # 0 @@ -26,14 +25,10 @@ class VimbaException(Exception): ERR_PARTIAL_REGISTER_ACCESS, # -50 to -56 - ERR_CAMERA_NOT_FOUND, ERR_FRAME_BUFFER_MEMORY, - ERR_INVALID_INPUT, - ERR_FEATURE_NOT_FOUND, - ERR_INTERFACE_NOT_FOUND, ERR_NOT_IMPLEMENTED_IN_PYMBA, ERR_UNDEFINED_ERROR_CODE, - ) = tuple(range(0, -20, -1)) + tuple(range(-50, -57, -1)) + ) = tuple(range(0, -20, -1)) + tuple(range(-50, -53, -1)) ERRORS = { # Vimba C API specific errors @@ -59,11 +54,7 @@ class VimbaException(Exception): ERR_PARTIAL_REGISTER_ACCESS: 'A multiple registers read or write was partially completed.', # Custom errors - ERR_CAMERA_NOT_FOUND: 'Could not find the specified camera.', ERR_FRAME_BUFFER_MEMORY: 'Not enough memory to assign frame buffer.', - ERR_INVALID_INPUT: 'Invalid input.', - ERR_FEATURE_NOT_FOUND: 'Could not find the specified feature.', - ERR_INTERFACE_NOT_FOUND: 'Could not find the specified interface.', ERR_NOT_IMPLEMENTED_IN_PYMBA: 'This function is not yet implemented in Pymba', ERR_UNDEFINED_ERROR_CODE: 'Undefined error code', } -- cgit v1.2.3 From 9d1561d6acdd83bb087d9e1a08ae5bfa3894b5e6 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 29 Jan 2019 10:39:56 +1100 Subject: cleanup setup params --- setup.py | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/setup.py b/setup.py index a4bc412..f21b1a1 100644 --- a/setup.py +++ b/setup.py @@ -1,32 +1,45 @@ from setuptools import setup +from pymba import PYMBA_VERSION -setup(name='pymba', - version=0.1, - description='pymba is a Python wrapper for the Allied Vision Technologies (AVT) Vimba C API.', - long_description='pymba is a Python wrapper for the Allied Vision Technologies (AVT) Vimba C API. It wraps the ' - 'VimbaC.dll file included in the AVT Vimba installation to provide a simple Python interface ' - 'for AVT cameras. It currently supports most of the functionality provided by VimbaC.dll.', + +setup(name='Pymba', + version=PYMBA_VERSION, + description="Pymba is a Python wrapper for Allied Vision's Vimba C API.", + long_description="Pymba is a Python wrapper for Allied Vision's Vimba C API. It wraps the VimbaC.dll file " + "included in the AVT Vimba installation to provide a simple Python interface for Allied Vision " + "cameras.", + # https://pypi.org/pypi?%3Aaction=list_classifiers classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', - 'Intended Audience :: Science/Research', + 'Intended Audience :: End Users/Desktop', + 'Intended Audience :: Healthcare Industry', 'Intended Audience :: Manufacturing', - 'License :: OSI Approved :: MIT License', + 'Intended Audience :: Science/Research', + 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', + 'Natural Language :: English', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', 'Topic :: Multimedia :: Graphics :: Capture :: Digital Camera', - 'Topic :: Multimedia :: Graphics :: Graphics Conversion', + 'Topic :: Multimedia :: Video :: Capture', 'Topic :: Scientific/Engineering :: Image Recognition', + 'Topic :: Scientific/Engineering :: Visualization', 'Topic :: Software Development :: Libraries :: Python Modules'], - keywords='python, opencv, cv, machine vision, computer vision, image recognition, vimba,' - 'allied vision technologies, avt', + keywords='python, python3, opencv, cv, machine vision, computer vision, image recognition, vimba, allied vision', author='morefigs', author_email='morefigs@gmail.com', url='https://github.com/morefigs/pymba', - license='MIT', + license='GPL-3.0', packages=['pymba', 'tests'], zip_safe=False, - requires=['numpy'], + install_requires=[ + 'numpy', + ], + extras_requires={ + 'dev': [ + 'pytest', + ] + } ) -- cgit v1.2.3 From 87e92e00c7e1faf92fffdcd8d025984461e0b859 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 29 Jan 2019 10:40:55 +1100 Subject: cleanup vimba object class --- pymba/vimba_object.py | 182 ++++++++++++++++++++------------------------------ 1 file changed, 71 insertions(+), 111 deletions(-) diff --git a/pymba/vimba_object.py b/pymba/vimba_object.py index f8d7c93..174fe9a 100644 --- a/pymba/vimba_object.py +++ b/pymba/vimba_object.py @@ -1,5 +1,5 @@ from ctypes import byref, sizeof, c_void_p, c_uint32, c_uint64, c_bool -from typing import Union, Tuple, List, Optional +from typing import List, Optional from .vimba_exception import VimbaException from .feature import Feature @@ -19,120 +19,90 @@ class VimbaObject: VMB_ACCESS_MODE_LITE = 8 def __init__(self, handle: Optional[int] = None): - if handle is None: - self._handle = c_void_p() - else: - self._handle = c_void_p(handle) - - # can't be populated until device is opened - self._vmb_features_info = None - - @property - def handle(self): - return self._handle - - # override getattr for undefined attributes - def __getattr__(self, attr): - # if a feature value requested (requires object (camera) open) - if attr in self.get_feature_names(): - return Feature(attr, self._handle).value + self._handle = c_void_p(handle) + self._features = {} - # otherwise don't know about it - raise AttributeError(''.join(["'VimbaObject' has no attribute '", attr, "'"])) + def __getattr__(self, item: str): + # allow direct access to feature values as an attribute + if item in self.feature_names(): + return self.feature(item).value - # override setattr for undefined attributes - def __setattr__(self, attr, val): + raise AttributeError(f'{self.__class__.__name__} object has no attribute {item}') - # set privates as normal - # check this first to allow all privates to set normally - # and avoid recursion errors - if attr.startswith('_'): - super(VimbaObject, self).__setattr__(attr, val) + # allow direct access to feature values as an attribute + def __setattr__(self, item: str, value): + # set privates as normally to avoid recursion errors + if item.startswith('_'): + super().__setattr__(item, value) - # if it's an actual camera feature (requires camera open) - elif attr in self.get_feature_names(): - Feature(attr, self._handle).value = val + # allow direct access to feature values as an attribute + elif item in self.feature_names(): + self.feature(item).value = value - # otherwise just set the attribute value as normal else: - super(VimbaObject, self).__setattr__(attr, val) + super().__setattr__(item, value) - def _get_feature_infos(self) -> List[vimba_c.VmbFeatureInfo]: + def _feature_infos(self) -> List[vimba_c.VmbFeatureInfo]: """ - Gets feature info of all available features. Will - cause error if object/camera is not opened. - - :returns: list -- feature info for available features. - """ - # check it's populated as can't populate it in __init__ - if self._vmb_features_info is None: - vmb_feature_info = vimba_c.VmbFeatureInfo() - num_found = c_uint32(-1) - - # call once to get number of available features - error = vimba_c.vmb_features_list(self._handle, - None, - 0, - byref(num_found), - sizeof(vmb_feature_info)) - if error: - raise VimbaException(error) - - # number of features specified by Vimba - num_features = num_found.value - vmb_feature_infos = (vimba_c.VmbFeatureInfo * num_features)() - - # call again to get the features - error = vimba_c.vmb_features_list(self._handle, - vmb_feature_infos, - num_features, - byref(num_found), - sizeof(vmb_feature_info)) - if error: - raise VimbaException(error) - - self._vmb_features_info = list(vmb_feature_info for vmb_feature_info in vmb_feature_infos) - - return self._vmb_features_info - - def get_feature_names(self) -> List[str]: + Gets feature info of all available features. Will cause error if object/camera/etc is not opened. """ - Get names of all available features. - """ - return list(feature_info.name for feature_info in self._get_feature_infos()) + # call once to get number of available features + vmb_feature_info = vimba_c.VmbFeatureInfo() + num_found = c_uint32(-1) + error = vimba_c.vmb_features_list(self._handle, + None, + 0, + byref(num_found), + sizeof(vmb_feature_info)) + if error: + raise VimbaException(error) + + # call again to get the features + num_features = num_found.value + vmb_feature_infos = (vimba_c.VmbFeatureInfo * num_features)() + error = vimba_c.vmb_features_list(self._handle, + vmb_feature_infos, + num_features, + byref(num_found), + sizeof(vmb_feature_info)) + if error: + raise VimbaException(error) - def get_feature_info(self, feature_name: str) -> vimba_c.VmbFeatureInfo: + return list(vmb_feature_info for vmb_feature_info in vmb_feature_infos) + + def _feature_info(self, feature_name: str) -> vimba_c.VmbFeatureInfo: """ Gets feature info object of specified feature. :param feature_name: the name of the feature. """ - # don't do this live as we already have this info - # return info object, if it exists - for vmb_feature_info in self._get_feature_infos(): - if vmb_feature_info.name == feature_name: + for vmb_feature_info in self._feature_infos(): + if feature_name == vmb_feature_info.name.decode(): return vmb_feature_info - # otherwise raise error - raise VimbaException(VimbaException.ERR_FEATURE_NOT_FOUND) + raise VimbaException(VimbaException.ERR_INSTANCE_NOT_FOUND) - # don't think we ever need to return a feature object... - # def getFeature(self, featureName): + def feature_names(self) -> List[str]: + """ + Get names of all available features. + """ + return list(vmb_feature_info.name.decode() + for vmb_feature_info in self._feature_infos()) - def get_feature_range(self, feature_name: str) -> Union[Tuple[float, float], Tuple[int, int], List[str]]: + def feature(self, feature_name: str) -> Feature: """ - Get valid range of feature values. - :param feature_name: name of the feature to query. - :returns: tuple -- range as (feature min value, feature max value, for int or float features only). - list -- names of possible enum values (for enum features only). + Gets feature object by name from the corresponding Vimba object. + :param feature_name: name of the feature to get. """ - # shouldn't cache this - return Feature(feature_name, self._handle).range + if feature_name in self._features: + return self._features[feature_name] + feature = Feature(feature_name, self._handle) + self._features[feature_name] = feature + return feature def run_feature_command(self, feature_name: str) -> None: """ Run a feature command. :param feature_name: the name of the feature. """ - # run a command error = vimba_c.vmb_feature_command_run(self._handle, feature_name.encode()) if error: @@ -148,24 +118,19 @@ class VimbaObject: return is_done.value + # todo test def read_register(self, address: int) -> int: - # note that the underlying Vimba function allows reading of an array - # of registers, but only one address/value at a time is implemented - # here + # note that the underlying Vimba function allows reading of an array of registers, but only one address/value + # at a time is implemented here """ Read from a register of the module (camera) and return its value. :param address: the address of the register to read. """ read_count = 1 - - # todo expects bytes not int - - reg_address = c_uint64(int(address, 16)) - + reg_address = c_uint64(address) reg_data = c_uint64() num_complete_reads = c_uint32() - - error = vimba_c.vmb_registers_read(self.handle, + error = vimba_c.vmb_registers_read(self._handle, read_count, byref(reg_address), byref(reg_data), @@ -175,25 +140,20 @@ class VimbaObject: return reg_data.value + # todo test def write_register(self, address: int, value: int) -> None: - # note that the underlying Vimba function allows writing of an array - # of registers, but only one address/value at a time is implemented - # here + # note that the underlying Vimba function allows writing of an array of registers, but only one address/value + # at a time is implemented here """ Write to a register of the module (camera). :param address: the address of the register to read. :param value: the value to set in hex. """ write_count = 1 - - # todo expects bytes not int - - reg_address = c_uint64(int(address, 16)) - reg_data = c_uint64(int(value, 16)) - + reg_address = c_uint64(address) + reg_data = c_uint64(value) num_complete_writes = c_uint32() - - error = vimba_c.vmb_registers_write(self.handle, + error = vimba_c.vmb_registers_write(self._handle, write_count, byref(reg_address), byref(reg_data), -- cgit v1.2.3 From c1ec035532eaab857eae891d3f3db130412f6ead Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 29 Jan 2019 11:04:10 +1100 Subject: handle property for frame --- pymba/camera.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pymba/camera.py b/pymba/camera.py index 979371b..c2bd574 100644 --- a/pymba/camera.py +++ b/pymba/camera.py @@ -65,6 +65,10 @@ class Camera(VimbaObject): self._camera_id = camera_id super().__init__() + @property + def handle(self): + return self._handle + @property def camera_id(self) -> str: return self._camera_id -- cgit v1.2.3 From 62c8247d16c619e615aca338a2053a177c5e955d Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 29 Jan 2019 11:09:22 +1100 Subject: typo --- pymba/camera.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pymba/camera.py b/pymba/camera.py index c2bd574..e15ba6d 100644 --- a/pymba/camera.py +++ b/pymba/camera.py @@ -36,8 +36,8 @@ def _camera_infos() -> List[vimba_c.VmbCameraInfo]: def _camera_info(id_string: str) -> vimba_c.VmbCameraInfo: """ Gets camera info object of specified camera. - :param cameraId: the ID of the camera object to get. This can be an ID or e.g. a serial number. Check the Vimba - documentation for other possible values. + :param id_string: the ID of the camera object to get. This can be an ID or e.g. a serial number. Check the Vimba + documentation for other possible values. """ vmb_camera_info = vimba_c.VmbCameraInfo() error = vimba_c.vmb_camera_info_query(id_string.encode(), -- cgit v1.2.3 From fe810f80b2571ec864afbd98a02c96720eeda43a Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 29 Jan 2019 12:31:56 +1100 Subject: formatting clean up --- setup.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index f21b1a1..2721f88 100644 --- a/setup.py +++ b/setup.py @@ -26,13 +26,17 @@ setup(name='Pymba', 'Topic :: Multimedia :: Video :: Capture', 'Topic :: Scientific/Engineering :: Image Recognition', 'Topic :: Scientific/Engineering :: Visualization', - 'Topic :: Software Development :: Libraries :: Python Modules'], + 'Topic :: Software Development :: Libraries :: Python Modules' + ], keywords='python, python3, opencv, cv, machine vision, computer vision, image recognition, vimba, allied vision', author='morefigs', author_email='morefigs@gmail.com', url='https://github.com/morefigs/pymba', license='GPL-3.0', - packages=['pymba', 'tests'], + packages=[ + 'pymba', + 'tests', + ], zip_safe=False, install_requires=[ 'numpy', -- cgit v1.2.3 From 2d86dcf99782bc4aa2dc769bde87ef50769b9482 Mon Sep 17 00:00:00 2001 From: morefigs Date: Tue, 29 Jan 2019 13:35:38 +1100 Subject: rename vimba as no longer import vimba module --- examples/get_camera.py | 4 ++-- examples/get_camera_feature_infos.py | 4 ++-- examples/get_camera_feature_names.py | 4 ++-- examples/get_camera_feature_values.py | 4 ++-- examples/get_camera_ids.py | 4 ++-- examples/get_interface.py | 4 ++-- examples/get_interface_feature_infos.py | 4 ++-- examples/get_interface_feature_names.py | 4 ++-- examples/get_interface_feature_values.py | 4 ++-- examples/get_interface_ids.py | 4 ++-- examples/get_system.py | 4 ++-- examples/get_system_feature_values.py | 4 ++-- examples/get_version.py | 4 ++-- examples/set_camera_feature_value.py | 4 ++-- examples/set_interface_feature_value.py | 4 ++-- 15 files changed, 30 insertions(+), 30 deletions(-) diff --git a/examples/get_camera.py b/examples/get_camera.py index 5a9285b..7a830f7 100644 --- a/examples/get_camera.py +++ b/examples/get_camera.py @@ -3,7 +3,7 @@ from pymba import Vimba if __name__ == '__main__': - with Vimba() as vmb: + with Vimba() as vimba: # provide camera index or id - camera = vmb.camera(0) + camera = vimba.camera(0) print(camera) diff --git a/examples/get_camera_feature_infos.py b/examples/get_camera_feature_infos.py index 78e2752..03ad935 100644 --- a/examples/get_camera_feature_infos.py +++ b/examples/get_camera_feature_infos.py @@ -3,8 +3,8 @@ from pymba import Vimba if __name__ == '__main__': - with Vimba() as vmb: - camera = vmb.camera(0) + with Vimba() as vimba: + camera = vimba.camera(0) camera.open() for feature_name in camera.feature_names(): diff --git a/examples/get_camera_feature_names.py b/examples/get_camera_feature_names.py index fcf6a8a..d3415dc 100644 --- a/examples/get_camera_feature_names.py +++ b/examples/get_camera_feature_names.py @@ -3,8 +3,8 @@ from pymba import Vimba if __name__ == '__main__': - with Vimba() as vmb: - camera = vmb.camera(0) + with Vimba() as vimba: + camera = vimba.camera(0) camera.open() for feature_name in camera.feature_names(): diff --git a/examples/get_camera_feature_values.py b/examples/get_camera_feature_values.py index 89f1582..33d454b 100644 --- a/examples/get_camera_feature_values.py +++ b/examples/get_camera_feature_values.py @@ -3,8 +3,8 @@ from pymba import Vimba, VimbaException if __name__ == '__main__': - with Vimba() as vmb: - camera = vmb.camera(0) + with Vimba() as vimba: + camera = vimba.camera(0) camera.open() # get feature value via feature object diff --git a/examples/get_camera_ids.py b/examples/get_camera_ids.py index fe37242..670d71f 100644 --- a/examples/get_camera_ids.py +++ b/examples/get_camera_ids.py @@ -3,5 +3,5 @@ from pymba import Vimba if __name__ == '__main__': - with Vimba() as vmb: - print(vmb.camera_ids()) + with Vimba() as vimba: + print(vimba.camera_ids()) diff --git a/examples/get_interface.py b/examples/get_interface.py index 331f650..0465223 100644 --- a/examples/get_interface.py +++ b/examples/get_interface.py @@ -3,7 +3,7 @@ from pymba import Vimba if __name__ == '__main__': - with Vimba() as vmb: + with Vimba() as vimba: # provide interface index or id - interface = vmb.interface(0) + interface = vimba.interface(0) print(interface) diff --git a/examples/get_interface_feature_infos.py b/examples/get_interface_feature_infos.py index 8330a3d..fefa079 100644 --- a/examples/get_interface_feature_infos.py +++ b/examples/get_interface_feature_infos.py @@ -3,8 +3,8 @@ from pymba import Vimba if __name__ == '__main__': - with Vimba() as vmb: - interface = vmb.interface(0) + with Vimba() as vimba: + interface = vimba.interface(0) interface.open() for feature_name in interface.feature_names(): diff --git a/examples/get_interface_feature_names.py b/examples/get_interface_feature_names.py index 36bf7be..6f0347d 100644 --- a/examples/get_interface_feature_names.py +++ b/examples/get_interface_feature_names.py @@ -3,8 +3,8 @@ from pymba import Vimba if __name__ == '__main__': - with Vimba() as vmb: - interface = vmb.interface(0) + with Vimba() as vimba: + interface = vimba.interface(0) interface.open() for feature_name in interface.feature_names(): diff --git a/examples/get_interface_feature_values.py b/examples/get_interface_feature_values.py index 335b477..fbb59b4 100644 --- a/examples/get_interface_feature_values.py +++ b/examples/get_interface_feature_values.py @@ -3,8 +3,8 @@ from pymba import Vimba, VimbaException if __name__ == '__main__': - with Vimba() as vmb: - interface = vmb.interface(0) + with Vimba() as vimba: + interface = vimba.interface(0) interface.open() # get feature value via feature object diff --git a/examples/get_interface_ids.py b/examples/get_interface_ids.py index 92df889..9a7cbec 100644 --- a/examples/get_interface_ids.py +++ b/examples/get_interface_ids.py @@ -3,5 +3,5 @@ from pymba import Vimba if __name__ == '__main__': - with Vimba() as vmb: - print(vmb.interface_ids()) + with Vimba() as vimba: + print(vimba.interface_ids()) diff --git a/examples/get_system.py b/examples/get_system.py index 2be6a09..2d59001 100644 --- a/examples/get_system.py +++ b/examples/get_system.py @@ -3,6 +3,6 @@ from pymba import Vimba if __name__ == '__main__': - with Vimba() as vmb: - system = vmb.system() + with Vimba() as vimba: + system = vimba.system() print(system) diff --git a/examples/get_system_feature_values.py b/examples/get_system_feature_values.py index c83f292..dd0d178 100644 --- a/examples/get_system_feature_values.py +++ b/examples/get_system_feature_values.py @@ -3,8 +3,8 @@ from pymba import Vimba, VimbaException if __name__ == '__main__': - with Vimba() as vmb: - system = vmb.system() + with Vimba() as vimba: + system = vimba.system() # get feature value via feature object for feature_name in system.feature_names(): diff --git a/examples/get_version.py b/examples/get_version.py index e03fe12..1542845 100644 --- a/examples/get_version.py +++ b/examples/get_version.py @@ -4,5 +4,5 @@ from pymba import Vimba, PYMBA_VERSION if __name__ == '__main__': print(f'Pymba version: {PYMBA_VERSION}') - vmb = Vimba() - print(f'Vimba version: {vmb.version}') + vimba = Vimba() + print(f'Vimba version: {vimba.version}') diff --git a/examples/set_camera_feature_value.py b/examples/set_camera_feature_value.py index a33bf88..020f264 100644 --- a/examples/set_camera_feature_value.py +++ b/examples/set_camera_feature_value.py @@ -3,8 +3,8 @@ from pymba import Vimba if __name__ == '__main__': - with Vimba() as vmb: - camera = vmb.camera(0) + with Vimba() as vimba: + camera = vimba.camera(0) camera.open() # set a feature value by feature name diff --git a/examples/set_interface_feature_value.py b/examples/set_interface_feature_value.py index 0fc80a2..f921c0c 100644 --- a/examples/set_interface_feature_value.py +++ b/examples/set_interface_feature_value.py @@ -3,8 +3,8 @@ from pymba import Vimba if __name__ == '__main__': - with Vimba() as vmb: - interface = vmb.interface(0) + with Vimba() as vimba: + interface = vimba.interface(0) interface.open() # set a feature value by feature name -- cgit v1.2.3 From 1c5ebb2ddd0f7b84e536a9acf3d534aaab12de06 Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 30 Jan 2019 11:39:52 +1100 Subject: added pixel format to byte mapping --- pymba/camera.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/pymba/camera.py b/pymba/camera.py index e15ba6d..322762a 100644 --- a/pymba/camera.py +++ b/pymba/camera.py @@ -7,6 +7,33 @@ from .frame import Frame from . import vimba_c +# todo update this to be more like VmbPixelFormatType in VmbCommonTypes.h +# Map pixel formats to bytes per pixel +PIXEL_FORMAT_BYTES = { + "Mono8": 1, + "Mono12": 2, + # todo untested + "Mono12Packed": 1.5, + "Mono14": 2, + "Mono16": 2, + "RGB8": 3, + "RGB8Packed": 3, + "BGR8Packed": 3, + "RGBA8Packed": 4, + "BGRA8Packed": 4, + # todo untested + "YUV411Packed": 4 / 3.0, + "YUV422Packed": 2, + "YUV444Packed": 3, + "BayerRG8": 1, + "BayerRG12": 2, + "BayerGR8": 1, + "BayerGR12": 2, + # todo untested + "BayerGR12Packed": 1.5, +} + + def _camera_infos() -> List[vimba_c.VmbCameraInfo]: """ Gets camera info of all attached cameras. -- cgit v1.2.3 From b3a357818fbf2a1ed87009d7ba1264a611339d05 Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 30 Jan 2019 11:40:16 +1100 Subject: remove untested comments --- pymba/camera.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pymba/camera.py b/pymba/camera.py index 322762a..3bdc16b 100644 --- a/pymba/camera.py +++ b/pymba/camera.py @@ -12,7 +12,6 @@ from . import vimba_c PIXEL_FORMAT_BYTES = { "Mono8": 1, "Mono12": 2, - # todo untested "Mono12Packed": 1.5, "Mono14": 2, "Mono16": 2, @@ -21,7 +20,6 @@ PIXEL_FORMAT_BYTES = { "BGR8Packed": 3, "RGBA8Packed": 4, "BGRA8Packed": 4, - # todo untested "YUV411Packed": 4 / 3.0, "YUV422Packed": 2, "YUV444Packed": 3, @@ -29,7 +27,6 @@ PIXEL_FORMAT_BYTES = { "BayerRG12": 2, "BayerGR8": 1, "BayerGR12": 2, - # todo untested "BayerGR12Packed": 1.5, } -- cgit v1.2.3 From 2465a09a4e1c57fb8d1aae98d242b2f4af0b53db Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 30 Jan 2019 11:41:55 +1100 Subject: update description to match readme --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 2721f88..429f77f 100644 --- a/setup.py +++ b/setup.py @@ -6,9 +6,9 @@ from pymba import PYMBA_VERSION setup(name='Pymba', version=PYMBA_VERSION, description="Pymba is a Python wrapper for Allied Vision's Vimba C API.", - long_description="Pymba is a Python wrapper for Allied Vision's Vimba C API. It wraps the VimbaC.dll file " - "included in the AVT Vimba installation to provide a simple Python interface for Allied Vision " - "cameras.", + long_description="Pymba is a Python wrapper for Allied Vision's Vimba C API. It wraps the VimbaC library file " + "included in the Vimba installation to provide a simple Python interface for Allied Vision " + "cameras. It currently supports most of the functionality provided by Vimba.", # https://pypi.org/pypi?%3Aaction=list_classifiers classifiers=[ 'Development Status :: 5 - Production/Stable', -- cgit v1.2.3 From 8a2b69353c3d11692f764121c1594b6c530596bd Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 30 Jan 2019 11:46:07 +1100 Subject: ignore scratch dir --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 8448e35..55ff08c 100644 --- a/.gitignore +++ b/.gitignore @@ -38,4 +38,5 @@ nosetests.xml .idea/ .cache/ -venv* \ No newline at end of file +venv* +scrap/ -- cgit v1.2.3 From 429d4743a984f681323926a5eca8018cadfbcb02 Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 30 Jan 2019 12:56:39 +1100 Subject: rename vimba as namespace is now clean --- tests/test_vimba.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/test_vimba.py b/tests/test_vimba.py index 27b3112..b1ef987 100644 --- a/tests/test_vimba.py +++ b/tests/test_vimba.py @@ -26,17 +26,17 @@ def test_startup_shutdown(): @pytest.fixture -def vmb() -> Vimba: - with Vimba() as vmb: +def vimba() -> Vimba: + with Vimba() as vimba: # for ethernet camera discovery - if vmb.system().GeVTLIsPresent: - vmb.system().run_feature_command("GeVDiscoveryAllOnce") - yield vmb + if vimba.system().GeVTLIsPresent: + vimba.system().run_feature_command("GeVDiscoveryAllOnce") + yield vimba -def test_interface_camera_ids(vmb: Vimba): +def test_interface_camera_ids(vimba: Vimba): # test id funcs return a list of strings (not bytes) - for func in (vmb.interface_ids, vmb.camera_ids): + for func in (vimba.interface_ids, vimba.camera_ids): ids = func() assert isinstance(ids, list) assert ids @@ -44,9 +44,9 @@ def test_interface_camera_ids(vmb: Vimba): assert isinstance(x, str) -def test_interface(vmb: Vimba): - interface = vmb.interface(vmb.interface_ids()[0]) +def test_interface(vimba: Vimba): + interface = vimba.interface(vimba.interface_ids()[0]) -def test_camera(vmb: Vimba): - camera = vmb.camera(vmb.camera_ids()[0]) +def test_camera(vimba: Vimba): + camera = vimba.camera(vimba.camera_ids()[0]) -- cgit v1.2.3 From 837d3af93e55b3a2714832092e1581df51cef1ec Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 30 Jan 2019 13:57:07 +1100 Subject: cleanup frame class --- pymba/frame.py | 127 ++++++++++++++++++--------------------------------------- 1 file changed, 39 insertions(+), 88 deletions(-) diff --git a/pymba/frame.py b/pymba/frame.py index e3f698b..5f9bcda 100644 --- a/pymba/frame.py +++ b/pymba/frame.py @@ -1,41 +1,12 @@ from ctypes import byref, sizeof, addressof, create_string_buffer, cast, POINTER, c_ubyte, c_void_p from typing import Optional, Callable -import warnings -try: - import numpy as np -except ImportError: - warnings.warn('could not import numpy, some Frame methods may not work.') +import numpy as np +from . import camera as _camera from .vimba_exception import VimbaException from . import vimba_c -# Map pixel formats to bytes per pixel -PIXEL_FORMATS = { - "Mono8": 1, - "Mono12": 2, - # untested - "Mono12Packed": 1.5, - "Mono14": 2, - "Mono16": 2, - "RGB8": 3, - "RGB8Packed": 3, - "BGR8Packed": 3, - "RGBA8Packed": 4, - "BGRA8Packed": 4, - # untested - "YUV411Packed": 4 / 3.0, - "YUV422Packed": 2, - "YUV444Packed": 3, - "BayerRG8": 1, - "BayerRG12": 2, - "BayerGR8": 1, - "BayerGR12": 2, - # untested - "BayerGR12Packed": 1.5, -} - - class MemoryBlock: """ A memory block object for dealing neatly with C memory allocations. @@ -52,59 +23,51 @@ class MemoryBlock: if self._block is None: raise VimbaException(VimbaException.ERR_FRAME_BUFFER_MEMORY) - def __del__(self): - del self._block - class Frame: """ A Vimba frame. """ - def __init__(self, camera: 'Camera'): + def __init__(self, camera: '_camera.Camera'): self._camera = camera - self._handle = camera.handle - # get frame sizes - self.payload_size = self._camera.PayloadSize - self.width = self._camera.Width - self.height = self._camera.Height - self.pixel_bytes = PIXEL_FORMATS[self._camera.PixelFormat] - - # frame structure - self._frame = vimba_c.VmbFrame() + self._vmb_frame = vimba_c.VmbFrame() self._c_mem = None + self._frame_callback = None + self._frame_callback_wrapper_c = None - def announce(self): + def announce(self) -> None: """ Announce frames to the API that may be queued for frame capturing later. Should be called after the frame is created. Call startCapture after this method. """ # keep this reference to keep block alive for life of frame - self._c_mem = MemoryBlock(self.payload_size) + self._c_mem = MemoryBlock(self._camera.PayloadSize) + # set buffer to have length of expected payload size - self._frame.buffer = self._c_mem.block + self._vmb_frame.buffer = self._c_mem.block # set buffer size to expected payload size - self._frame.bufferSize = self.payload_size + self._vmb_frame.bufferSize = self._camera.PayloadSize - error = vimba_c.vmb_frame_announce(self._handle, - byref(self._frame), - sizeof(self._frame)) + error = vimba_c.vmb_frame_announce(self._camera.handle, + byref(self._vmb_frame), + sizeof(self._vmb_frame)) if error: raise VimbaException(error) - def revoke(self): + def revoke(self) -> None: """ Revoke a frame from the API. """ - error = vimba_c.vmb_frame_revoke(self._handle, - byref(self._frame)) + error = vimba_c.vmb_frame_revoke(self._camera.handle, + byref(self._vmb_frame)) if error: raise VimbaException(error) - def queue_capture(self, frame_callback: Optional[Callable] = None) -> None: + def queue_for_capture(self, frame_callback: Optional[Callable] = None) -> None: """ Queue frames that may be filled during frame capturing. Call after announceFrame and startCapture. Callback must accept argument of type frame. Remember to requeue the frame by calling frame.queue_capture() at the end @@ -124,53 +87,41 @@ class Frame: # keep a reference to prevent gc issues self._frame_callback_wrapper_c = vimba_c.vmb_frame_callback_func(frame_callback_wrapper) - error = vimba_c.vmb_capture_frame_queue(self._handle, - byref(self._frame), + error = vimba_c.vmb_capture_frame_queue(self._camera.handle, + byref(self._vmb_frame), self._frame_callback_wrapper_c) if error: raise VimbaException(error) - def wait_capture(self, timeout_ms: Optional[int] = 2000) -> int: + def wait_for_capture(self, timeout_ms: Optional[int] = 2000) -> None: """ Wait for a queued frame to be filled (or dequeued). Call after an acquisition command. :param timeout_ms: time out in milliseconds. """ - error = vimba_c.vmb_capture_frame_wait(self._handle, - byref(self._frame), + error = vimba_c.vmb_capture_frame_wait(self._camera.handle, + byref(self._vmb_frame), timeout_ms) + if error: + raise VimbaException(error) - # error to be processed by the end user for this function. - # Prevents system for breaking for example on a hardware trigger timeout - - # todo raise error instead? - - return error - - def get_buffer_data(self): + def image_pointer(self): """ - Retrieve buffer data in a useful format. + Get a pointer to the frame's image data as a ctypes c_ubyte array pointer. """ + return cast(self._vmb_frame.buffer, POINTER(c_ubyte * self._vmb_frame.bufferSize)) - # todo simplify? - - # cast frame buffer memory contents to a usable type - data = cast(self._frame.buffer, POINTER(c_ubyte * self.payload_size)) - - # make array of c_ubytes from buffer - image_bytes = int(self.height * self.width * self.pixel_bytes) - return (c_ubyte * image_bytes).from_address(addressof(data.contents)) - - def get_image(self): + def image_buffer(self): """ - Returns the frame's image data as a NumPy array. + Get a copy of the frame's image data as a ctypes c_ubyte array. """ - data = cast(self._frame.buffer, POINTER(c_ubyte * self._frame.imageSize)) - return np.ndarray(buffer=data.contents, dtype=np.uint8, shape=(self._frame.height, self._frame.width)) + return self.image_pointer().contents - @property - def timestamp(self) -> int: - return self._frame.timestamp + def image_numpy_array(self) -> np.ndarray: + """ + Get the frame's image data as a NumPy array, which can be used with OpenCV. + """ + # todo pixel formats larger than 8-bit - @property - def receive_status(self) -> int: - return self._frame.receiveStatus + return np.ndarray(buffer=self.image_buffer(), + dtype=np.uint8, + shape=(self._vmb_frame.height, self._vmb_frame.width)) -- cgit v1.2.3 From 01587d8ba4d5a1f8371f44e719eda6547d3ed459 Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 30 Jan 2019 13:59:01 +1100 Subject: clean up examples into separate dirs --- examples/camera/get_camera_object.py | 9 +++++ examples/camera/list_camera_ids.py | 7 ++++ examples/camera/list_feature_infos.py | 14 +++++++ examples/camera/list_feature_names.py | 13 +++++++ examples/camera/list_feature_values_and_ranges.py | 34 +++++++++++++++++ examples/camera/opencv_capture_image.py | 34 +++++++++++++++++ .../camera/opencv_capture_image_with_callback.py | 44 ++++++++++++++++++++++ examples/camera/write_feature_value.py | 22 +++++++++++ examples/get_camera.py | 9 ----- examples/get_camera_feature_infos.py | 14 ------- examples/get_camera_feature_names.py | 13 ------- examples/get_camera_feature_values.py | 27 ------------- examples/get_camera_ids.py | 7 ---- examples/get_interface.py | 9 ----- examples/get_interface_feature_infos.py | 14 ------- examples/get_interface_feature_names.py | 13 ------- examples/get_interface_feature_values.py | 27 ------------- examples/get_interface_ids.py | 7 ---- examples/get_system.py | 8 ---- examples/get_system_feature_values.py | 24 ------------ examples/get_version.py | 8 ---- examples/interface/get_interface_object.py | 9 +++++ examples/interface/list_feature_infos.py | 14 +++++++ examples/interface/list_feature_names.py | 13 +++++++ .../interface/list_feature_values_and_ranges.py | 33 ++++++++++++++++ examples/interface/list_interface_ids.py | 7 ++++ examples/interface/write_feature_value.py | 22 +++++++++++ examples/set_camera_feature_value.py | 18 --------- examples/set_interface_feature_value.py | 19 ---------- examples/show_version.py | 8 ++++ examples/system/get_system_object.py | 8 ++++ examples/system/list_feature_values_and_ranges.py | 30 +++++++++++++++ 32 files changed, 321 insertions(+), 217 deletions(-) create mode 100644 examples/camera/get_camera_object.py create mode 100644 examples/camera/list_camera_ids.py create mode 100644 examples/camera/list_feature_infos.py create mode 100644 examples/camera/list_feature_names.py create mode 100644 examples/camera/list_feature_values_and_ranges.py create mode 100644 examples/camera/opencv_capture_image.py create mode 100644 examples/camera/opencv_capture_image_with_callback.py create mode 100644 examples/camera/write_feature_value.py delete mode 100644 examples/get_camera.py delete mode 100644 examples/get_camera_feature_infos.py delete mode 100644 examples/get_camera_feature_names.py delete mode 100644 examples/get_camera_feature_values.py delete mode 100644 examples/get_camera_ids.py delete mode 100644 examples/get_interface.py delete mode 100644 examples/get_interface_feature_infos.py delete mode 100644 examples/get_interface_feature_names.py delete mode 100644 examples/get_interface_feature_values.py delete mode 100644 examples/get_interface_ids.py delete mode 100644 examples/get_system.py delete mode 100644 examples/get_system_feature_values.py delete mode 100644 examples/get_version.py create mode 100644 examples/interface/get_interface_object.py create mode 100644 examples/interface/list_feature_infos.py create mode 100644 examples/interface/list_feature_names.py create mode 100644 examples/interface/list_feature_values_and_ranges.py create mode 100644 examples/interface/list_interface_ids.py create mode 100644 examples/interface/write_feature_value.py delete mode 100644 examples/set_camera_feature_value.py delete mode 100644 examples/set_interface_feature_value.py create mode 100644 examples/show_version.py create mode 100644 examples/system/get_system_object.py create mode 100644 examples/system/list_feature_values_and_ranges.py diff --git a/examples/camera/get_camera_object.py b/examples/camera/get_camera_object.py new file mode 100644 index 0000000..7a830f7 --- /dev/null +++ b/examples/camera/get_camera_object.py @@ -0,0 +1,9 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vimba: + # provide camera index or id + camera = vimba.camera(0) + print(camera) diff --git a/examples/camera/list_camera_ids.py b/examples/camera/list_camera_ids.py new file mode 100644 index 0000000..670d71f --- /dev/null +++ b/examples/camera/list_camera_ids.py @@ -0,0 +1,7 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vimba: + print(vimba.camera_ids()) diff --git a/examples/camera/list_feature_infos.py b/examples/camera/list_feature_infos.py new file mode 100644 index 0000000..03ad935 --- /dev/null +++ b/examples/camera/list_feature_infos.py @@ -0,0 +1,14 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vimba: + camera = vimba.camera(0) + camera.open() + + for feature_name in camera.feature_names(): + feature = camera.feature(feature_name) + print(feature.info) + + camera.close() diff --git a/examples/camera/list_feature_names.py b/examples/camera/list_feature_names.py new file mode 100644 index 0000000..d3415dc --- /dev/null +++ b/examples/camera/list_feature_names.py @@ -0,0 +1,13 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vimba: + camera = vimba.camera(0) + camera.open() + + for feature_name in camera.feature_names(): + print(feature_name) + + camera.close() diff --git a/examples/camera/list_feature_values_and_ranges.py b/examples/camera/list_feature_values_and_ranges.py new file mode 100644 index 0000000..353d48e --- /dev/null +++ b/examples/camera/list_feature_values_and_ranges.py @@ -0,0 +1,34 @@ +from pymba import Vimba, VimbaException + + +if __name__ == '__main__': + + with Vimba() as vimba: + camera = vimba.camera(0) + camera.open() + + # get feature value via feature object + for feature_name in camera.feature_names(): + feature = camera.feature(feature_name) + + try: + value = feature.value + range_ = feature.range + + # alternatively the feature value can be read as an object attribute + # value = getattr(camera, feature_name) + # or + # value = camera.someFeatureName + + except VimbaException as e: + value = e + range_ = None + + print('\n\t'.join( + str(x) for x in ( + feature_name, + f'value: {value}', + f'range: {range_}') + if x is not None)) + + camera.close() diff --git a/examples/camera/opencv_capture_image.py b/examples/camera/opencv_capture_image.py new file mode 100644 index 0000000..e8bf3d5 --- /dev/null +++ b/examples/camera/opencv_capture_image.py @@ -0,0 +1,34 @@ +import cv2 +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vimba: + camera = vimba.camera(0) + camera.open() + + # setup camera and frame and capture a single image + camera.AcquisitionMode = 'SingleFrame' + frame = camera.create_frame() + frame.announce() + camera.start_capture() + frame.queue_for_capture() + camera.run_feature_command('AcquisitionStart') + camera.run_feature_command('AcquisitionStop') + frame.wait_for_capture() + + # get the image data as a numpy array + image = frame.image_numpy_array() + + # display image + cv2.imshow(camera.camera_id, image) + # waits for user to close image + cv2.waitKey(0) + + # stop capturing and clean up + camera.end_capture() + camera.flush_capture_queue() + camera.revoke_all_frames() + + camera.close() diff --git a/examples/camera/opencv_capture_image_with_callback.py b/examples/camera/opencv_capture_image_with_callback.py new file mode 100644 index 0000000..4d5fa28 --- /dev/null +++ b/examples/camera/opencv_capture_image_with_callback.py @@ -0,0 +1,44 @@ +from time import sleep +import cv2 +from pymba import Vimba +from pymba.frame import Frame + + +def on_callback(completed_frame: Frame): + print('Callback called!') + + # get the image data as a numpy array + image = completed_frame.image_numpy_array() + + # display image + cv2.imshow(camera.camera_id, image) + # waits for user to close image + cv2.waitKey(0) + + +if __name__ == '__main__': + + with Vimba() as vimba: + camera = vimba.camera(0) + camera.open() + + # setup camera and frame and capture a single image + camera.AcquisitionMode = 'SingleFrame' + frame = camera.create_frame() + frame.announce() + camera.start_capture() + frame.queue_for_capture(on_callback) + camera.run_feature_command('AcquisitionStart') + camera.run_feature_command('AcquisitionStop') + + # wait long enough for the frame callback to be called + for _ in range(100): + sleep(0.1) + print('.', end='') + + # stop capturing and clean up + camera.end_capture() + camera.flush_capture_queue() + camera.revoke_all_frames() + + camera.close() diff --git a/examples/camera/write_feature_value.py b/examples/camera/write_feature_value.py new file mode 100644 index 0000000..77f8ce5 --- /dev/null +++ b/examples/camera/write_feature_value.py @@ -0,0 +1,22 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vimba: + camera = vimba.camera(0) + camera.open() + + # read a feature value + feature = camera.feature('ExposureAuto') + value = feature.value + + # set the feature value + feature.value = value + + print(feature.name, '=', feature.value) + + # alternatively the feature value can be set as an object attribute + camera.ExposureAuto = feature.value + + camera.close() diff --git a/examples/get_camera.py b/examples/get_camera.py deleted file mode 100644 index 7a830f7..0000000 --- a/examples/get_camera.py +++ /dev/null @@ -1,9 +0,0 @@ -from pymba import Vimba - - -if __name__ == '__main__': - - with Vimba() as vimba: - # provide camera index or id - camera = vimba.camera(0) - print(camera) diff --git a/examples/get_camera_feature_infos.py b/examples/get_camera_feature_infos.py deleted file mode 100644 index 03ad935..0000000 --- a/examples/get_camera_feature_infos.py +++ /dev/null @@ -1,14 +0,0 @@ -from pymba import Vimba - - -if __name__ == '__main__': - - with Vimba() as vimba: - camera = vimba.camera(0) - camera.open() - - for feature_name in camera.feature_names(): - feature = camera.feature(feature_name) - print(feature.info) - - camera.close() diff --git a/examples/get_camera_feature_names.py b/examples/get_camera_feature_names.py deleted file mode 100644 index d3415dc..0000000 --- a/examples/get_camera_feature_names.py +++ /dev/null @@ -1,13 +0,0 @@ -from pymba import Vimba - - -if __name__ == '__main__': - - with Vimba() as vimba: - camera = vimba.camera(0) - camera.open() - - for feature_name in camera.feature_names(): - print(feature_name) - - camera.close() diff --git a/examples/get_camera_feature_values.py b/examples/get_camera_feature_values.py deleted file mode 100644 index 33d454b..0000000 --- a/examples/get_camera_feature_values.py +++ /dev/null @@ -1,27 +0,0 @@ -from pymba import Vimba, VimbaException - - -if __name__ == '__main__': - - with Vimba() as vimba: - camera = vimba.camera(0) - camera.open() - - # get feature value via feature object - for feature_name in camera.feature_names(): - feature = camera.feature(feature_name) - - try: - value = feature.value - - # alternatively the feature value can be read as an object attribute - # value = getattr(camera, feature_name) - # or - # value = camera.someFeatureName - - except VimbaException as e: - value = e - - print(feature_name, '--', value) - - camera.close() diff --git a/examples/get_camera_ids.py b/examples/get_camera_ids.py deleted file mode 100644 index 670d71f..0000000 --- a/examples/get_camera_ids.py +++ /dev/null @@ -1,7 +0,0 @@ -from pymba import Vimba - - -if __name__ == '__main__': - - with Vimba() as vimba: - print(vimba.camera_ids()) diff --git a/examples/get_interface.py b/examples/get_interface.py deleted file mode 100644 index 0465223..0000000 --- a/examples/get_interface.py +++ /dev/null @@ -1,9 +0,0 @@ -from pymba import Vimba - - -if __name__ == '__main__': - - with Vimba() as vimba: - # provide interface index or id - interface = vimba.interface(0) - print(interface) diff --git a/examples/get_interface_feature_infos.py b/examples/get_interface_feature_infos.py deleted file mode 100644 index fefa079..0000000 --- a/examples/get_interface_feature_infos.py +++ /dev/null @@ -1,14 +0,0 @@ -from pymba import Vimba - - -if __name__ == '__main__': - - with Vimba() as vimba: - interface = vimba.interface(0) - interface.open() - - for feature_name in interface.feature_names(): - feature = interface.feature(feature_name) - print(feature.info) - - interface.close() diff --git a/examples/get_interface_feature_names.py b/examples/get_interface_feature_names.py deleted file mode 100644 index 6f0347d..0000000 --- a/examples/get_interface_feature_names.py +++ /dev/null @@ -1,13 +0,0 @@ -from pymba import Vimba - - -if __name__ == '__main__': - - with Vimba() as vimba: - interface = vimba.interface(0) - interface.open() - - for feature_name in interface.feature_names(): - print(feature_name) - - interface.close() diff --git a/examples/get_interface_feature_values.py b/examples/get_interface_feature_values.py deleted file mode 100644 index fbb59b4..0000000 --- a/examples/get_interface_feature_values.py +++ /dev/null @@ -1,27 +0,0 @@ -from pymba import Vimba, VimbaException - - -if __name__ == '__main__': - - with Vimba() as vimba: - interface = vimba.interface(0) - interface.open() - - # get feature value via feature object - for feature_name in interface.feature_names(): - feature = interface.feature(feature_name) - - try: - value = feature.value - - # alternatively the feature value can be read as an object attribute - # value = getattr(interface, feature_name) - # or - # value = interface.someFeatureName - - except VimbaException as e: - value = e - - print(feature_name, '--', value) - - interface.close() diff --git a/examples/get_interface_ids.py b/examples/get_interface_ids.py deleted file mode 100644 index 9a7cbec..0000000 --- a/examples/get_interface_ids.py +++ /dev/null @@ -1,7 +0,0 @@ -from pymba import Vimba - - -if __name__ == '__main__': - - with Vimba() as vimba: - print(vimba.interface_ids()) diff --git a/examples/get_system.py b/examples/get_system.py deleted file mode 100644 index 2d59001..0000000 --- a/examples/get_system.py +++ /dev/null @@ -1,8 +0,0 @@ -from pymba import Vimba - - -if __name__ == '__main__': - - with Vimba() as vimba: - system = vimba.system() - print(system) diff --git a/examples/get_system_feature_values.py b/examples/get_system_feature_values.py deleted file mode 100644 index dd0d178..0000000 --- a/examples/get_system_feature_values.py +++ /dev/null @@ -1,24 +0,0 @@ -from pymba import Vimba, VimbaException - - -if __name__ == '__main__': - - with Vimba() as vimba: - system = vimba.system() - - # get feature value via feature object - for feature_name in system.feature_names(): - feature = system.feature(feature_name) - - try: - value = feature.value - - # alternatively the feature value can be read as an object attribute - # value = getattr(system, feature_name) - # or - # value = system.someFeatureName - - except VimbaException as e: - value = e - - print(feature_name, '--', value) diff --git a/examples/get_version.py b/examples/get_version.py deleted file mode 100644 index 1542845..0000000 --- a/examples/get_version.py +++ /dev/null @@ -1,8 +0,0 @@ -from pymba import Vimba, PYMBA_VERSION - - -if __name__ == '__main__': - print(f'Pymba version: {PYMBA_VERSION}') - - vimba = Vimba() - print(f'Vimba version: {vimba.version}') diff --git a/examples/interface/get_interface_object.py b/examples/interface/get_interface_object.py new file mode 100644 index 0000000..0465223 --- /dev/null +++ b/examples/interface/get_interface_object.py @@ -0,0 +1,9 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vimba: + # provide interface index or id + interface = vimba.interface(0) + print(interface) diff --git a/examples/interface/list_feature_infos.py b/examples/interface/list_feature_infos.py new file mode 100644 index 0000000..fefa079 --- /dev/null +++ b/examples/interface/list_feature_infos.py @@ -0,0 +1,14 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vimba: + interface = vimba.interface(0) + interface.open() + + for feature_name in interface.feature_names(): + feature = interface.feature(feature_name) + print(feature.info) + + interface.close() diff --git a/examples/interface/list_feature_names.py b/examples/interface/list_feature_names.py new file mode 100644 index 0000000..6f0347d --- /dev/null +++ b/examples/interface/list_feature_names.py @@ -0,0 +1,13 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vimba: + interface = vimba.interface(0) + interface.open() + + for feature_name in interface.feature_names(): + print(feature_name) + + interface.close() diff --git a/examples/interface/list_feature_values_and_ranges.py b/examples/interface/list_feature_values_and_ranges.py new file mode 100644 index 0000000..b33c76a --- /dev/null +++ b/examples/interface/list_feature_values_and_ranges.py @@ -0,0 +1,33 @@ +from pymba import Vimba, VimbaException + + +if __name__ == '__main__': + + with Vimba() as vimba: + interface = vimba.interface(0) + interface.open() + + # get feature value via feature object + for feature_name in interface.feature_names(): + feature = interface.feature(feature_name) + try: + value = feature.value + range_ = feature.range + + # alternatively the feature value can be read as an object attribute + # value = getattr(interface, feature_name) + # or + # value = interface.someFeatureName + + except VimbaException as e: + value = e + range_ = None + + print('\n\t'.join( + str(x) for x in ( + feature_name, + f'value: {value}', + f'range: {range_}') + if x is not None)) + + interface.close() diff --git a/examples/interface/list_interface_ids.py b/examples/interface/list_interface_ids.py new file mode 100644 index 0000000..9a7cbec --- /dev/null +++ b/examples/interface/list_interface_ids.py @@ -0,0 +1,7 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vimba: + print(vimba.interface_ids()) diff --git a/examples/interface/write_feature_value.py b/examples/interface/write_feature_value.py new file mode 100644 index 0000000..0c71da2 --- /dev/null +++ b/examples/interface/write_feature_value.py @@ -0,0 +1,22 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vimba: + interface = vimba.interface(0) + interface.open() + + # set a feature value by feature name + feature = interface.feature('InterfacePingPace') + value = feature.value + + # set the feature value + feature.value = value + + print(feature.name, '=', feature.value) + + # alternatively the feature value can be set as an object attribute + interface.InterfacePingPace = 3 + + interface.close() diff --git a/examples/set_camera_feature_value.py b/examples/set_camera_feature_value.py deleted file mode 100644 index 020f264..0000000 --- a/examples/set_camera_feature_value.py +++ /dev/null @@ -1,18 +0,0 @@ -from pymba import Vimba - - -if __name__ == '__main__': - - with Vimba() as vimba: - camera = vimba.camera(0) - camera.open() - - # set a feature value by feature name - feature = camera.feature('ExposureAuto') - print(feature.value) - feature.value = feature.value - - # alternatively the feature value can be set as an object attribute - camera.ExposureAuto = feature.value - - camera.close() diff --git a/examples/set_interface_feature_value.py b/examples/set_interface_feature_value.py deleted file mode 100644 index f921c0c..0000000 --- a/examples/set_interface_feature_value.py +++ /dev/null @@ -1,19 +0,0 @@ -from pymba import Vimba - - -if __name__ == '__main__': - - with Vimba() as vimba: - interface = vimba.interface(0) - interface.open() - - # set a feature value by feature name - feature = interface.feature('InterfacePingPace') - print(feature.value) - feature.value = 3 - print(feature.value) - - # alternatively the feature value can be set as an object attribute - interface.InterfacePingPace = 3 - - interface.close() diff --git a/examples/show_version.py b/examples/show_version.py new file mode 100644 index 0000000..1542845 --- /dev/null +++ b/examples/show_version.py @@ -0,0 +1,8 @@ +from pymba import Vimba, PYMBA_VERSION + + +if __name__ == '__main__': + print(f'Pymba version: {PYMBA_VERSION}') + + vimba = Vimba() + print(f'Vimba version: {vimba.version}') diff --git a/examples/system/get_system_object.py b/examples/system/get_system_object.py new file mode 100644 index 0000000..2d59001 --- /dev/null +++ b/examples/system/get_system_object.py @@ -0,0 +1,8 @@ +from pymba import Vimba + + +if __name__ == '__main__': + + with Vimba() as vimba: + system = vimba.system() + print(system) diff --git a/examples/system/list_feature_values_and_ranges.py b/examples/system/list_feature_values_and_ranges.py new file mode 100644 index 0000000..ef4da34 --- /dev/null +++ b/examples/system/list_feature_values_and_ranges.py @@ -0,0 +1,30 @@ +from pymba import Vimba, VimbaException + + +if __name__ == '__main__': + + with Vimba() as vimba: + system = vimba.system() + + # get feature value via feature object + for feature_name in system.feature_names(): + feature = system.feature(feature_name) + try: + value = feature.value + range_ = feature.range + + # alternatively the feature value can be read as an object attribute + # value = getattr(system, feature_name) + # or + # value = system.someFeatureName + + except VimbaException as e: + value = e + range_ = None + + print('\n\t'.join( + str(x) for x in ( + feature_name, + f'value: {value}', + f'range: {range_}') + if x is not None)) -- cgit v1.2.3 From 6d6fc471aceff5802fc3ad5db3d35521e87abf4c Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 30 Jan 2019 13:59:23 +1100 Subject: delete outdates tests --- tests/opencv_example.py | 76 ----------------------------- tests/opencv_liveview_example.py | 79 ------------------------------ tests/opencv_liveview_example_color.py | 89 ---------------------------------- tests/test_cameras.py | 72 --------------------------- tests/test_enumfeature.py | 25 ---------- tests/test_installation.py | 9 ---- tests/test_interfaces.py | 28 ----------- tests/test_systemfeature.py | 20 -------- 8 files changed, 398 deletions(-) delete mode 100644 tests/opencv_example.py delete mode 100644 tests/opencv_liveview_example.py delete mode 100644 tests/opencv_liveview_example_color.py delete mode 100644 tests/test_cameras.py delete mode 100644 tests/test_enumfeature.py delete mode 100644 tests/test_installation.py delete mode 100644 tests/test_interfaces.py delete mode 100644 tests/test_systemfeature.py diff --git a/tests/opencv_example.py b/tests/opencv_example.py deleted file mode 100644 index edc6a5d..0000000 --- a/tests/opencv_example.py +++ /dev/null @@ -1,76 +0,0 @@ -from __future__ import absolute_import, print_function, division -from pymba import * -import numpy as np -import cv2 -import time - -#very crude example, assumes your camera is PixelMode = BAYERRG8 - -# start Vimba -with Vimba() as vimba: - # get system object - system = vimba.getSystem() - - # list available cameras (after enabling discovery for GigE cameras) - if system.GeVTLIsPresent: - system.run_feature_command("GeVDiscoveryAllOnce") - time.sleep(0.2) - cameraIds = vimba.getCameraIds() - for cameraId in cameraIds: - print('Camera ID:', cameraId) - - # get and open a camera - camera0 = vimba.getCamera(cameraIds[0]) - camera0.open() - - # list camera features - cameraFeatureNames = camera0.get_feature_names() - for name in cameraFeatureNames: - print('Camera feature:', name) - - # read info of a camera feature - #featureInfo = camera0.getFeatureInfo('AcquisitionMode') - #for field in featInfo.getFieldNames(): - # print field, '--', getattr(featInfo, field) - - # get the value of a feature - print(camera0.AcquisitionMode) - - # set the value of a feature - camera0.AcquisitionMode = 'SingleFrame' - - # create new frames for the camera - frame0 = camera0.create_frame() # creates a frame - frame1 = camera0.create_frame() # creates a second frame - - # announce frame - frame0.announce() - - # capture a camera image - count = 0 - while count < 10: - camera0.start_capture() - frame0.queue_capture() - camera0.run_feature_command('AcquisitionStart') - camera0.run_feature_command('AcquisitionStop') - frame0.wait_capture() - - # get image data... - imgData = frame0.get_buffer() - - moreUsefulImgData = np.ndarray(buffer = frame0.get_buffer(), - dtype = np.uint8, - shape = (frame0.height, - frame0.width, - 1)) - rgb = cv2.cvtColor(moreUsefulImgData, cv2.COLOR_BAYER_RG2RGB) - cv2.imwrite('foo{}.png'.format(count), rgb) - print("image {} saved".format(count)) - count += 1 - camera0.end_capture() - # clean up after capture - camera0.revoke_all_frames() - - # close camera - camera0.close() - diff --git a/tests/opencv_liveview_example.py b/tests/opencv_liveview_example.py deleted file mode 100644 index 9c83264..0000000 --- a/tests/opencv_liveview_example.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Mon Jul 07 14:59:03 2014 - -@author: derricw -""" - -from __future__ import absolute_import, print_function, division -from pymba import * -import numpy as np -import cv2 -import time - -cv2.namedWindow("test") - -with Vimba() as vimba: - system = vimba.getSystem() - - system.run_feature_command("GeVDiscoveryAllOnce") - time.sleep(0.2) - - camera_ids = vimba.getCameraIds() - - for cam_id in camera_ids: - print("Camera found: ", cam_id) - - c0 = vimba.getCamera(camera_ids[0]) - c0.open() - - try: - #gigE camera - print(c0.GevSCPSPacketSize) - print(c0.StreamBytesPerSecond) - c0.StreamBytesPerSecond = 100000000 - except: - #not a gigE camera - pass - - #set pixel format - c0.PixelFormat="Mono8" - #c0.ExposureTimeAbs=60000 - - frame = c0.create_frame() - frame.announce() - - c0.start_capture() - - framecount = 0 - droppedframes = [] - - while 1: - try: - frame.queue_capture() - success = True - except: - droppedframes.append(framecount) - success = False - c0.run_feature_command("AcquisitionStart") - c0.run_feature_command("AcquisitionStop") - frame.wait_capture(1000) - frame_data = frame.get_buffer() - if success: - img = np.ndarray(buffer=frame_data, - dtype=np.uint8, - shape=(frame.height,frame.width,1)) - cv2.imshow("test",img) - framecount+=1 - k = cv2.waitKey(1) - if k == 0x1b: - cv2.destroyAllWindows() - print("Frames displayed: %i"%framecount) - print("Frames dropped: %s"%droppedframes) - break - - - c0.end_capture() - c0.revoke_all_frames() - - c0.close() diff --git a/tests/opencv_liveview_example_color.py b/tests/opencv_liveview_example_color.py deleted file mode 100644 index e2e2379..0000000 --- a/tests/opencv_liveview_example_color.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Mon Jul 07 14:59:03 2014 - -@author: derricw - -Same as the other liveview example, but displays in color. - -Obviously you want to use a camera that has a color mode like BGR8Packed - -OpenCV is expecting color images to be in BGR8Packed by default. It can work - with other formats as well as convert one to the other, but this example - just uses its default behavior. - -""" -from __future__ import absolute_import, print_function, division -from pymba import * -import numpy as np -import cv2 -import time -import sys - -cv2.namedWindow("test") - -with Vimba() as vimba: - system = vimba.getSystem() - - system.run_feature_command("GeVDiscoveryAllOnce") - time.sleep(0.2) - - camera_ids = vimba.getCameraIds() - - for cam_id in camera_ids: - print("Camera found: ", cam_id) - - c0 = vimba.getCamera(camera_ids[0]) - c0.open() - - try: - #gigE camera - print("Packet size:", c0.GevSCPSPacketSize) - c0.StreamBytesPerSecond = 100000000 - print("BPS:", c0.StreamBytesPerSecond) - except: - #not a gigE camera - pass - - #set pixel format - c0.PixelFormat = "BGR8Packed" # OPENCV DEFAULT - time.sleep(0.2) - - frame = c0.create_frame() - frame.announce() - - c0.start_capture() - - framecount = 0 - droppedframes = [] - - while 1: - try: - frame.queue_capture() - success = True - except: - droppedframes.append(framecount) - success = False - c0.run_feature_command("AcquisitionStart") - c0.run_feature_command("AcquisitionStop") - frame.wait_capture(1000) - frame_data = frame.get_buffer() - if success: - img = np.ndarray(buffer=frame_data, - dtype=np.uint8, - shape=(frame.height, frame.width, frame.pixel_bytes)) - cv2.imshow("test", img) - framecount += 1 - k = cv2.waitKey(1) - if k == 0x1b: - cv2.destroyAllWindows() - print("Frames displayed: %i" % framecount) - print("Frames dropped: %s" % droppedframes) - break - - - c0.end_capture() - c0.revoke_all_frames() - - c0.close() - diff --git a/tests/test_cameras.py b/tests/test_cameras.py deleted file mode 100644 index 7879ce8..0000000 --- a/tests/test_cameras.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/python -from __future__ import absolute_import, print_function, division -from pymba import * -import time - - -def test_cameras(): - # start Vimba - with Vimba() as vimba: - # get system object - system = vimba.getSystem() - - # list available cameras (after enabling discovery for GigE cameras) - if system.GeVTLIsPresent: - system.run_feature_command("GeVDiscoveryAllOnce") - time.sleep(0.2) - - cameraIds = vimba.getCameraIds() - for cameraId in cameraIds: - print('Camera ID:', cameraId) - - # get and open a camera - camera0 = vimba.getCamera(cameraIds[0]) - camera0.open() - - # list camera features - cameraFeatureNames = camera0.get_feature_names() - for name in cameraFeatureNames: - print('Camera feature:', name) - - # get the value of a feature - print(camera0.AcquisitionMode) - - # set the value of a feature - camera0.AcquisitionMode = 'SingleFrame' - - # create new frames for the camera - frame0 = camera0.create_frame() # creates a frame - frame1 = camera0.create_frame() # creates a second frame - - # announce frame - frame0.announce() - - # capture a camera image - camera0.start_capture() - frame0.queue_capture() - camera0.run_feature_command('AcquisitionStart') - camera0.run_feature_command('AcquisitionStop') - frame0.wait_capture() - - # get image data... - imgData = frame0.get_buffer() - - # ...or use NumPy for fast image display (for use with OpenCV, etc) - import numpy as np - - moreUsefulImgData = np.ndarray(buffer=frame0.get_buffer(), - dtype=np.uint8, - shape=(frame0.height, - frame0.width, - 1)) - - # clean up after capture - camera0.end_capture() - camera0.revoke_all_frames() - - # close camera - camera0.close() - - -if __name__ == '__main__': - test_cameras() \ No newline at end of file diff --git a/tests/test_enumfeature.py b/tests/test_enumfeature.py deleted file mode 100644 index 0744820..0000000 --- a/tests/test_enumfeature.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/python -from __future__ import absolute_import, print_function, division -from pymba import * - - -def test_enumfeature(): - # get system object - with Vimba() as vimba: - system = vimba.getSystem() - - # get enum value - print ("get enum value (DiscoveryCameraEvent): '%s'" % (system.DiscoveryCameraEvent)) - - # get enum range - range = system.get_feature_range('DiscoveryCameraEvent') - print ("get enum value range (DiscoveryCameraEvent): '%s'" % (str(range))) - - # set enum value - #print ("setting enum value (DiscoveryCameraEvent)...") - #system.DiscoveryCameraEvent = 'Unreachable' - #print ("enum value (DiscoveryCameraEvent)set to '%s'." % (system.DiscoveryCameraEvent.value)) - - -if __name__ == '__main__': - test_enumfeature() \ No newline at end of file diff --git a/tests/test_installation.py b/tests/test_installation.py deleted file mode 100644 index 06af7d6..0000000 --- a/tests/test_installation.py +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/python -from __future__ import absolute_import, print_function, division -from pymba import Vimba - - -def test_installation(): - with Vimba() as vimba: - version = vimba.getVersion() - assert version == '1.2.0' diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py deleted file mode 100644 index 3fc4a94..0000000 --- a/tests/test_interfaces.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/python -from __future__ import absolute_import, print_function, division -from pymba import * -import time - - -def test_interfaces(): - # start Vimba - with Vimba() as vimba: - # get list of available interfaces - interfaceIds = vimba.getInterfaceIds() - for interfaceId in interfaceIds: - print('Interface ID:', interfaceId) - - # get interface object and open it - interface0 = vimba.getInterface(interfaceIds[0]) - interface0.open() - - # list interface features - interfaceFeatureNames = interface0.get_feature_names() - for name in interfaceFeatureNames: - print('Interface feature:', name) - - # close interface - interface0.close() - -if __name__ == '__main__': - test_interfaces() \ No newline at end of file diff --git a/tests/test_systemfeature.py b/tests/test_systemfeature.py deleted file mode 100644 index f61d55d..0000000 --- a/tests/test_systemfeature.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/python -from __future__ import absolute_import, print_function, division -from pymba import * - - -def test_systemfeature(): - # get system object - with Vimba() as vimba: - system = vimba.getSystem() - - # list system features - for featureName in system.get_feature_names(): - print('System feature:', featureName) - fInfo = system.get_feature_info(featureName) - for field in fInfo.getFieldNames(): - print("\t", featureName, ":", field, getattr(fInfo, field)) - - -if __name__ == '__main__': - test_systemfeature() \ No newline at end of file -- cgit v1.2.3 From 193a223b4ea29150db5f2b44b415669520b1e080 Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 30 Jan 2019 14:25:20 +1100 Subject: Update README.md --- README.md | 172 ++++++++++++-------------------------------------------------- 1 file changed, 32 insertions(+), 140 deletions(-) diff --git a/README.md b/README.md index 90cfee1..3e1fe2d 100644 --- a/README.md +++ b/README.md @@ -1,155 +1,47 @@ -# pymba - -pymba is a Python wrapper for the Allied Vision Technologies (AVT) Vimba C API. It wraps the VimbaC.dll file included in the AVT Vimba installation to provide a simple Python interface for AVT cameras. It currently supports most of the functionality provided by VimbaC.dll. +# Pymba + +Pymba is a Python wrapper for Allied Vision's Vimba C API. It wraps the VimbaC library file included in the Vimba installation to provide a simple Python interface for Allied Vision cameras. It currently supports most of the functionality provided by Vimba. + +## Requirements + +### Vimba SDK + +* Download and run the Vimba SDK installer from Allied Vision from https://www.alliedvision.com/en/products/software.html. +* Select "Custom Selection". +* Select (at least) the following options: + * A transport layer that matches your hardware (e.g. "Vimba USB Transport Layer" for USB cameras) + * Core components + * Register GenICam Path variable + * Vimba SDK + * Core components + * Register environment variables + * C API runtime components + * C API development components + * Driver Installer + * Vimba Viewer +* Run `VimbaDriverInstaller.exe` and install the relevant driver. +* Test the driver installation by running `VimbaViewer.exe`. ## Installation -Install the Vimba SDK from AVT to the default directory. - -Run the AVTDriverInstaller tool and install the AVT Vimba SDK drivers. - -Install pymba. +Install Pymba via PIP: -## Usage + pip install pymba -### Testing installation +## Testing installation If Vimba and pymba are installed correctly, then the following code examples should give the installed Vimba version. No camera is needed. -Checking the version using a context manager: - - from pymba import * - - with Vimba() as vimba: - print(vimba.getVersion()) - -Or without using a context manager: - - from pymba import * - - vimba = Vimba() - vimba.startup() - print(vimba.getVersion()) - vimba.shutdown() - -### Interacting with cameras - -Discover, open, manipulate, and capture frames from a camera. - - from pymba import * - import time - - # start Vimba - with Vimba() as vimba: - # get system object - system = vimba.getSystem() - - # list available cameras (after enabling discovery for GigE cameras) - if system.GeVTLIsPresent: - system.runFeatureCommand("GeVDiscoveryAllOnce") - time.sleep(0.2) - cameraIds = vimba.getCameraIds() - for cameraId in cameraIds: - print(cameraId) - - # get and open a camera - camera0 = vimba.getCamera(cameraIds[0]) - camera0.openCamera() - - # list camera features - cameraFeatureNames = camera0.getFeatureNames() - for name in cameraFeatureNames: - print(name) - - # get the value of a feature - print(camera0.AcquisitionMode) - - # set the value of a feature - camera0.AcquisitionMode = 'SingleFrame' - - # create new frames for the camera - frame0 = camera0.getFrame() # creates a frame - frame1 = camera0.getFrame() # creates a second frame - - # announce frame - frame0.announceFrame() - - # capture a camera image - camera0.startCapture() - frame0.queueFrameCapture() - camera0.runFeatureCommand('AcquisitionStart') - camera0.runFeatureCommand('AcquisitionStop') - frame0.waitFrameCapture() - - # get image data... - imgData = frame0.getBufferByteData() - - # ...or use NumPy for fast image display (for use with OpenCV, etc) - import numpy as np - moreUsefulImgData = np.ndarray(buffer = frame0.getBufferByteData(), - dtype = np.uint8, - shape = (frame0.height, - frame0.width, - 1)) - - # clean up after capture - camera0.endCapture() - camera0.revokeAllFrames() - - # close camera - -### Interacting with the Vimba system - -Get a reference to the Vimba system object and list available system features. - - from pymba import * - - with Vimba() as vimba: - # get system object - system = vimba.getSystem() - - # list system features - for featureName in system.getFeatureNames(): - print(featureName) - -### Interacting with transport layer interfaces + from pymba import Vimba -Get a reference to an interface object and list available interface features. + print(Vimba.version()) - from pymba import * +## Usage examples - with Vimba() as vimba: - # get list of available interfaces - interfaceIds = vimba.getInterfaceIds() - for interfaceId in interfaceIds: - print(interfaceId) - - # get interface object and open it - interface0 = vimba.getInterface(interfaceIds[0]) - interface0.openInterface() - - # list interface features - interfaceFeatureNames = interface0.getFeatureNames() - for name in interfaceFeatureNames: - print(name) - - # close interface - interface0.closeInterface() - - - -### Handling Vimba exceptions - - from pymba import * - - try: - with Vimba() as vimba: - except VimbaException as e: - print(e.message) - - +Usage examples can be found in the [examples/](examples/) directory. ## Known issues -* Not all API functions are wrapped (most are). For full list see vimbadll.py. +* Not all API functions are supported. +* Not all camera pixel formats are currently supported. -- cgit v1.2.3 From aff8f4aa4a6f5b2bde153c4537693f768f9d7e1b Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 30 Jan 2019 14:26:35 +1100 Subject: Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3e1fe2d..bf5c017 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Pymba is a Python wrapper for Allied Vision's Vimba C API. It wraps the VimbaC l ## Installation -Install Pymba via PIP: +Install Pymba via PIP. pip install pymba @@ -38,7 +38,7 @@ If Vimba and pymba are installed correctly, then the following code examples sho ## Usage examples -Usage examples can be found in the [examples/](examples/) directory. +Usage examples can be found in [examples/](examples/). ## Known issues -- cgit v1.2.3 From cbceaff013690eecec2298b14810ef9e643770f2 Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 30 Jan 2019 14:27:49 +1100 Subject: make version a staticmethod --- pymba/vimba.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/pymba/vimba.py b/pymba/vimba.py index 795e03f..02c29c7 100644 --- a/pymba/vimba.py +++ b/pymba/vimba.py @@ -13,7 +13,19 @@ class Vimba: Python wrapper for Allied Vision's Vimba C API. """ - # todo - assign camera info and feature info as own object properties + @staticmethod + def version() -> str: + """ + Retrieve the version number of the Vimba C API. + """ + vmb_version_info = vimba_c.VmbVersionInfo() + error = vimba_c.vmb_version_query(vmb_version_info, sizeof(vmb_version_info)) + if error: + raise VimbaException(error) + + return '.'.join(str(x) for x in (vmb_version_info.major, + vmb_version_info.minor, + vmb_version_info.patch)) def __init__(self): # create own system singleton object @@ -36,20 +48,6 @@ class Vimba: """ self.shutdown() - @property - def version(self) -> str: - """ - Retrieve the version number of the Vimba C API. - """ - vmb_version_info = vimba_c.VmbVersionInfo() - error = vimba_c.vmb_version_query(vmb_version_info, sizeof(vmb_version_info)) - if error: - raise VimbaException(error) - - return '.'.join(str(x) for x in (vmb_version_info.major, - vmb_version_info.minor, - vmb_version_info.patch)) - def startup(self): """ Initialize the Vimba C API. -- cgit v1.2.3 From 810b1f0a061988b451f9d425d8788596ae39118b Mon Sep 17 00:00:00 2001 From: morefigs Date: Wed, 30 Jan 2019 14:28:00 +1100 Subject: update version example --- examples/show_version.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/show_version.py b/examples/show_version.py index 1542845..643dc1c 100644 --- a/examples/show_version.py +++ b/examples/show_version.py @@ -3,6 +3,4 @@ from pymba import Vimba, PYMBA_VERSION if __name__ == '__main__': print(f'Pymba version: {PYMBA_VERSION}') - - vimba = Vimba() - print(f'Vimba version: {vimba.version}') + print(f'Vimba version: {Vimba.version()}') -- cgit v1.2.3