VimbaPython icon indicating copy to clipboard operation
VimbaPython copied to clipboard

VimbaCError(<VmbError.MoreData: -9>)

Open gautamvenugopalan opened this issue 2 years ago • 3 comments

I'm running the following code snippet (grabNFrames, which repeatedly calls the function take_image) in order to capture images at a regular interval (every two seconds). I'm running vimba 1.1.0, and the hardware I'm using is an Alvium 1240.

def grabNFrames(dirname, nFrames=10, tSleep=10):
    try:
        lastIndex = int(getLastIndex(dirname=dirname))
    except:
        lastIndex=0
    for ii in range(nFrames):
        print(f'{ii}/{nFrames}')
        fname = f'{dirname}img_{ii+lastIndex+1}.npy'
        take_image(fname)
        sleep(tSleep)
    return()


def getLastIndex(dirname):
    fnames = glob.glob(dirname+'*.npy')
    fnames.sort(key=lambda f: int(re.sub('\D','',f)))
    lastFile = fnames[-1].split(sep='\\')[-1]
    return(re.sub('\D','', lastFile))

def take_image(filename):
    try:
        os.makedirs(os.path.dirname(filename))
    except:
        pass
    with Vimba.get_instance() as vimba:
        with vimba.get_camera_by_id('DEV_1AB22C013993') as camera:
            try:
                print(f'Commected to {camera.get_model()}')
                camera.ExposureTime.set(30)
                camera.Gain.set(27)
                camera.set_pixel_format(PixelFormat.Mono10p)
                frame = camera.get_frame()
                frame.convert_pixel_format(PixelFormat.Mono16)
                img = frame.as_numpy_ndarray()
            except VimbaCameraError as e:
                print(f'Did you quit the vimba viewer for the camera being accessed???')
                print(e)
              
    np.save(f'{filename}',img)  
    return(None)

I believe I have appropriate error handling structure, but I repeatedly get the following error - I'm not sure what to make of this "MoreData" error? After all, the function successfully executes for ~1000 instances before failing (though that number isn't a specific fixed quantity as far as I can tell in my limited trials). How can I avoid this issue / debug further?

---> 47     with Vimba.get_instance() as vimba:
     48         #cams = vimba.get_all_cameras()
     49         #DEV_000F314CC481

~\Anaconda3\lib\site-packages\vimba\util\tracer.py in wrapper(*args, **kwargs)
    132
    133             else:
--> 134                 return func(*args, **kwargs)
    135
    136         return wrapper

~\Anaconda3\lib\site-packages\vimba\vimba.py in __enter__(self)
     80         def __enter__(self):
     81             if not self.__context_cnt:
---> 82                 self._startup()
     83
     84             self.__context_cnt += 1

~\Anaconda3\lib\site-packages\vimba\util\tracer.py in wrapper(*args, **kwargs)
    132
    133             else:
--> 134                 return func(*args, **kwargs)
    135
    136         return wrapper

~\Anaconda3\lib\site-packages\vimba\util\context_decorator.py in wrapper(*args, **kwargs)
     42         def wrapper(*args, **kwargs):
     43             args[0]._context_entered = True
---> 44             return func(*args, **kwargs)
     45
     46         return wrapper

~\Anaconda3\lib\site-packages\vimba\vimba.py in _startup(self)
    483
    484             self.__inters = discover_interfaces()
--> 485             self.__cams = discover_cameras(self.__nw_discover)
    486             self.__feats = discover_features(G_VIMBA_C_HANDLE)
    487             attach_feature_accessors(self, self.__feats)

~\Anaconda3\lib\site-packages\vimba\util\tracer.py in wrapper(*args, **kwargs)
    132
    133             else:
--> 134                 return func(*args, **kwargs)
    135
    136         return wrapper

~\Anaconda3\lib\site-packages\vimba\camera.py in discover_cameras(network_discovery)
    998
    999         call_vimba_c('VmbCamerasList', cams_infos, cams_count, byref(cams_found),
-> 1000                      sizeof(VmbCameraInfo))
   1001
   1002         for info in cams_infos[:cams_found.value]:

~\Anaconda3\lib\site-packages\vimba\util\tracer.py in wrapper(*args, **kwargs)
    132
    133             else:
--> 134                 return func(*args, **kwargs)
    135
    136         return wrapper

~\Anaconda3\lib\site-packages\vimba\c_binding\vimba_c.py in call_vimba_c(func_name, *args)
    751     """
    752     global _lib_instance
--> 753     getattr(_lib_instance, func_name)(*args)
    754
    755

~\Anaconda3\lib\site-packages\vimba\c_binding\vimba_c.py in _eval_vmberror(result, func, *args)
    669 def _eval_vmberror(result: VmbError, func: Callable[..., Any], *args: Tuple[Any, ...]):
    670     if result not in (VmbError.Success, None):
--> 671         raise VimbaCError(result)
    672
    673

VimbaCError: VimbaCError(<VmbError.MoreData: -9>)

gautamvenugopalan avatar Aug 31 '22 20:08 gautamvenugopalan

Hello,

VmbErrorMoreData -9 means "More data available in a string/list than space is provided". I have not encountered this error before in my own code, but if I had to guess blindly I would say the pixel format conversion could be the source of the error. There are known issues with the conversion of pixels, that will be fixed in the new version. You can check #114 for more in dept information and some workarounds. To quote: "once convert_pixel_format is called on an instance of Frame, that object is changed in such a way, that it should ideally not be reused for frame transmissions". So to first copy the frame and then do the conversion.

For a more informed debugging, you can enable logging (see part 7.2 Logging in the Vimba Python manual).

Hope that helps, Teresa

Teresa-AlliedVision avatar Sep 01 '22 06:09 Teresa-AlliedVision

Hello Teresa,

Thank you for your suggestions! I tried making a copy (copy.deepcopy as suggested in #114) of the grabbed frame object - however, the error persists. Then, I tried further simplifying by omitting the Pixel conversion altogether:

def take_image(filename):
    try:
        os.makedirs(os.path.dirname(filename))
    except:
        pass
    with Vimba.get_instance() as vimba:
        with vimba.get_camera_by_id('DEV_1AB22C013993') as camera:
            try:
                print(f'Connected to {camera.get_model()}')
                camera.ExposureTime.set(30)
                camera.Gain.set(27)
                camera.set_pixel_format(PixelFormat.Mono8)
                frame = camera.get_frame()
                frameCopy = copy.deepcopy(frame)
                img = frameCopy.as_numpy_ndarray()
            except VimbaCameraError as e:
                print(f'Did you quit the vimba viewer for the camera being accessed???')
                print(e)
              
    np.save(f'{filename}',img)  
    return(None)

So now there really is no pixel conversion or any other operation going on, and yet, I continue to get the same error:

VimbaCError: VimbaCError(<VmbError.MoreData: -9>)

I'll give enabling logging a go...

gautamvenugopalan avatar Sep 02 '22 06:09 gautamvenugopalan

Hello, I asked my collegue, because this error is pretty rare and it seems unlikely that the source of the error comes from your code itself, but instead from the transmission. That means that most likely somewhere between host and camera (probably when reading or writing a feature), information is lost. Your application doesn't use a lot of bandwidth so there should be no data loss due to the system being overloaded, which is why I would suspect the cable. In case of packages belonging to a frame getting dropped, you will just get a frame with the status "incomplete". So that should not be the source of this specific error. What cable are you using and at what length? If you can, try swapping it out and/or try to verify that it works well, by checking the quality of the connection via throughput limit.

How to check the quality of transmission via bandwidth of a system:

  • Open the camera in VimbaViewer
  • Check that the feature "AcquisitionFrameRateEnable" is set to false, to disable frame rate limit. Set the exposure time to a value that is lower than 1/(max FPS). [optional, if you're not on default settings: set ROI to full and disable binning]
  • Set "DeviceLinkThroughputLimit" to the maximum value
  • Stream frames and see if there are dropped or incomplete frames (at the bottom of the viewer window are FPS displays: What FPS arrive at the host and what FPS are sent by the camera. Both should be the same.)
  • If there are dropped and incomplete frames, lower the throughput limit until all frames are received complete

-> that is the bandwidth of the current system, i.e. the borderline case to check against

  • if you can stream at full throughput limit, the connection is obviously ok. In that case, I would ask for some more info on your setup to see if the error can be reproduced on our end.

  • if you don't get to full TPL, swap out pieces of the system to find the bottleneck (in this case the suspect would be the cable)

Cheers, Teresa

Teresa-AlliedVision avatar Sep 05 '22 08:09 Teresa-AlliedVision