<commit_before>"""
Python wrapper for functionality exposed in the TemcaGraph dll.

@author: jayb

"""
from ctypes import *
import logging
import threading
import time
import os
import numpy as np
from numpy.ctypeslib import ndpointer

if __debug__:
    rel = "../x64/Debug/TemcaGraphDLL.dll"
else:
    rel = "../x64/Release/TemcaGraphDLL.dll"

dll_path = os.path.join(os.path.dirname(__file__), rel)

class StatusCallbackInfo(Structure):
    _fields_ = [
        ("status", c_int), 
        # -1 : fatal error
        # 0: finishied init (startup), 
        # 1: starting new frame, 
        # 2: finished frame capture  (ie. time to move the stage), 
        # 3: finished frame processing and file writing, 
        # 4: finished fini (shutdown)
        ("error_code", c_int),
        ("error_string", c_char * 256)
        ]

STATUSCALLBACKFUNC = CFUNCTYPE(c_int, POINTER(StatusCallbackInfo))  # returns c_int

class CameraInfo(Structure):
    _fields_ = [
        ("width", c_int),
        ("height", c_int),
        ("format", c_int),
        ("pixel_depth", c_int),
        ("camera_bpp", c_int),
        ("camera_model", c_char * 256),
        ("camera_id", c_char * 256)
        ]

class FocusInfo(Structure):
    _fields_ = [
        ("score", c_float),
        ("astigmatism", c_float),
        ("angle", c_float),
        ]

class ROIInfo(Structure):
    _fields_ = [
        ("gridX", c_int),
        ("gridY", c_int),
        ]

class TemcaGraphDLL(object):
    """
    dll setup.  These are all the foreign functions we are going to be using
        from the dll, along with their arguments types and return values.
    """
    _TemcaGraphDLL = WinDLL(dll_path)

    init = _TemcaGraphDLL.init
    init.argtypes = [c_char_p, STATUSCALLBACKFUNC]
    init.restype = c_uint32

    fini = _TemcaGraphDLL.fini

    camera_info = _TemcaGraphDLL.getCameraInfo
    camera_info.restype = CameraInfo

    grab_frame = _TemcaGraphDLL.grabFrame
    grab_frame.argtypes = [c_char_p, c_int, c_int]
    grab_frame.restype = None
    
    get_last_frame = _TemcaGraphDLL.getLastFrame
    get_last_frame.argtypes = [ndpointer(c_uint16, flags="C_CONTIGUOUS")]
    get_last_frame.restype = None

    get_status = _TemcaGraphDLL.getStatus
    get_status.restype = StatusCallbackInfo

    setRoiInfo = _TemcaGraphDLL.setROI
    setRoiInfo .restype = None
    setRoiInfo .argtypes = [ POINTER( ROIInfo) ]

class TemcaGraph(object):
    '''
    Wrapper for the C++ TemcaGraphDLL
    '''
    def __init__(self,):
        '''
        Most class variables are created in the init function
        '''
        self.aborting = False
        self.eventInitCompleted = threading.Event()
        self.eventStartNewFrame = threading.Event()
        self.eventCaptureCompleted = threading.Event()
        self.eventProcessingCompleted = threading.Event()
        self.eventFiniCompleted = threading.Event()

    def init(self,  graphType='default', callback=None):
        ''' 
        graphType: 'default', 'dummy'
        '''
        if callback == None:
            callback = self.statusCallback
        # prevent the callback from being garbage collected !!!
        self.callback = STATUSCALLBACKFUNC(callback)

        t = time.clock()
        if not TemcaGraphDLL.init(graphType, self.callback):
            raise EnvironmentError('Cannot create graphType: ' + graphType + '. Other possiblities: camera, is offline, not installed, or already in use')
        logging.info("TemcaGraph DLL initialized in %s seconds" % (time.clock() - t))

    def fini(self):
        ''' 
        Close down all graphs.
        '''
        TemcaGraphDLL.fini()

    def get_camera_info(self):
        ''' 
        Fills CameraInfo structure with details of the capture format including width, height, and bytes per pixel.
        '''
        ci = TemcaGraphDLL.camera_info()
        #self.frame_width = ci.width
        #self.frame_height = ci.height
        return ci

    def get_status(self):
        return TemcaGraphDLL.get_status()

    def grab_frame(self, filename = "none", roiX = 0, roiY = 0):
        ''' Trigger capture of a frame. '''
        TemcaGraphDLL.grab_frame(filename, roiX, roiY)

    def get_last_frame(self, img):
        ''' 
        Get a copy of the last frame captured as an ndarray.  
        This must be called only after eventCaptureCompleted has signaled.
        '''
        #assert (img.shape() == (3840, 3840) && im.type() == uint16])
        TemcaGraphDLL.get_last_frame(img)
        pass

    def set_roi_info (self, roiInfo):
        TemcaGraphDLL.setRoiInfo (roiInfo)

    def statusCallback (self, statusInfo):
        ''' Called by the c++ Temca graph runner whenever status changes:
            status values:
               -1: fatal error
                0: finishied init (startup)
                1: starting new frame
                2: finished frame capture  (ie. time to move the stage)
                3: finished frame processing and file writing
                4: finished fini (shutdown)
                ...
        '''
        status = statusInfo.contents.status
        error = statusInfo.contents.error_code
        logging.info ('callback status: ' + str(status) + ', error: ' + str(error))
        tid = threading.currentThread()
        if (status == -1):
            self.aborting = True
            error_string = statusInfo.contents.error_string
            logging.error ('callback error is' + error_string)
            return False
        elif status == 0:
            self.eventInitCompleted.set()
        elif status == 1:
            self.eventProcessingCompleted.clear()
            self.eventStartNewFrame.set()
        elif status == 2:
            self.eventCaptureCompleted.set()
        elif status == 3:
            self.eventCaptureCompleted.clear()
            self.eventStartNewFrame.clear()
            self.eventProcessingCompleted.set()
        elif status == 4:
            self.eventFiniCompleted.set()
        return True
    

if __name__ == '__main__':
     
    import cv2
    import numpy as np


    logging.basicConfig(level=logging.INFO,
                format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    temcaGraph = TemcaGraph()
    temcaGraph.init()
    #temcaGraph.init('dummy')

    # get info about frame dimensions<commit_msg>Comments<commit_after>"""
Python wrapper for functionality exposed in the TemcaGraph dll.

@author: jayb

"""
from ctypes import *
import logging
import threading
import time
import os
import numpy as np
from numpy.ctypeslib import ndpointer

if __debug__:
    rel = "../x64/Debug/TemcaGraphDLL.dll"
else:
    rel = "../x64/Release/TemcaGraphDLL.dll"

dll_path = os.path.join(os.path.dirname(__file__), rel)

class StatusCallbackInfo(Structure):
    _fields_ = [
        ("status", c_int), 
        # -1 : fatal error
        # 0: finishied init (startup), 
        # 1: starting new frame, 
        # 2: finished frame capture  (ie. time to move the stage), 
        # 3: finished frame processing and file writing, 
        # 4: finished fini (shutdown)
        ("error_code", c_int),
        ("error_string", c_char * 256)
        ]

STATUSCALLBACKFUNC = CFUNCTYPE(c_int, POINTER(StatusCallbackInfo))  # returns c_int

class CameraInfo(Structure):
    _fields_ = [
        ("width", c_int),
        ("height", c_int),
        ("format", c_int),
        ("pixel_depth", c_int),
        ("camera_bpp", c_int),
        ("camera_model", c_char * 256),
        ("camera_id", c_char * 256)
        ]

class FocusInfo(Structure):
    _fields_ = [
        ("score", c_float),
        ("astigmatism", c_float),
        ("angle", c_float),
        ]

class ROIInfo(Structure):
    _fields_ = [
        ("gridX", c_int),
        ("gridY", c_int),
        ]

class TemcaGraphDLL(object):
    """
    dll setup.  These are all the foreign functions we are going to be using
        from the dll, along with their arguments types and return values.
    """
    _TemcaGraphDLL = WinDLL(dll_path)

    init = _TemcaGraphDLL.init
    init.argtypes = [c_char_p, STATUSCALLBACKFUNC]
    init.restype = c_uint32

    fini = _TemcaGraphDLL.fini

    camera_info = _TemcaGraphDLL.getCameraInfo
    camera_info.restype = CameraInfo

    grab_frame = _TemcaGraphDLL.grabFrame
    grab_frame.argtypes = [c_char_p, c_int, c_int]
    grab_frame.restype = None
    
    get_last_frame = _TemcaGraphDLL.getLastFrame
    get_last_frame.argtypes = [ndpointer(c_uint16, flags="C_CONTIGUOUS")]
    get_last_frame.restype = None

    get_status = _TemcaGraphDLL.getStatus
    get_status.restype = StatusCallbackInfo

    setRoiInfo = _TemcaGraphDLL.setROI
    setRoiInfo .restype = None
    setRoiInfo .argtypes = [ POINTER( ROIInfo) ]

class TemcaGraph(object):
    '''
    Wrapper for the C++ TemcaGraphDLL
    '''
    def __init__(self,):
        '''
        Most class variables are created in the init function
        '''
        self.aborting = False
        self.eventInitCompleted = threading.Event()
        self.eventStartNewFrame = threading.Event()
        self.eventCaptureCompleted = threading.Event()
        self.eventProcessingCompleted = threading.Event()
        self.eventFiniCompleted = threading.Event()

    def init(self,  graphType='default', callback=None):
        ''' 
        graphType: 'default', 'dummy'
        '''
        if callback == None:
            callback = self.statusCallback
        # prevent the callback from being garbage collected !!!
        self.callback = STATUSCALLBACKFUNC(callback)

        t = time.clock()
        if not TemcaGraphDLL.init(graphType, self.callback):
            raise EnvironmentError('Cannot create graphType: ' + graphType + '. Other possiblities: camera, is offline, not installed, or already in use')
        logging.info("TemcaGraph DLL initialized in %s seconds" % (time.clock() - t))

    def fini(self):
        ''' 
        Close down all graphs.
        '''
        TemcaGraphDLL.fini()

    def get_camera_info(self):
        ''' 
        Fills CameraInfo structure with details of the capture format including width, height, and bytes per pixel.
        '''
        ci = TemcaGraphDLL.camera_info()
        #self.frame_width = ci.width
        #self.frame_height = ci.height
        return ci

    def get_status(self):
        return TemcaGraphDLL.get_status()

    def grab_frame(self, filename = "none", roiX = 0, roiY = 0):
        ''' Trigger capture of a frame. '''
        TemcaGraphDLL.grab_frame(filename, roiX, roiY)

    def get_last_frame(self, img):
        ''' 
        Get a copy of the last frame captured as an ndarray.  
        This must be called only after eventCaptureCompleted has signaled.
        '''
        #assert (img.shape() == (3840, 3840) && im.type() == uint16])
        TemcaGraphDLL.get_last_frame(img)
        pass

    def set_roi_info (self, roiInfo):
        TemcaGraphDLL.setRoiInfo (roiInfo)

    def statusCallback (self, statusInfo):
        ''' Called by the c++ Temca graph runner whenever status changes:
            status values:
               -1: fatal error
                0: finishied init (startup)
                1: starting new frame
                2: finished frame capture  (ie. time to move the stage)
                3: finished frame processing and file writing
                4: finished fini (shutdown)
                ...
        '''
        status = statusInfo.contents.status
        error = statusInfo.contents.error_code
        logging.info ('callback status: ' + str(status) + ', error: ' + str(error))
        tid = threading.currentThread()
        if (status == -1):
            self.aborting = True
            error_string = statusInfo.contents.error_string
            logging.error ('callback error is' + error_string)
            return False
        elif status == 0:
            # finished initialization of all graphs
            self.eventInitCompleted.set()
        elif status == 1:
            # ready to start the next frame
            self.eventProcessingCompleted.clear()
            self.eventStartNewFrame.set()
        elif status == 2:
            # capture frame is now available
            # (move the stage now)
            self.eventCaptureCompleted.set()
        elif status == 3:
            # all processing for the frame is complete
            self.eventCaptureCompleted.clear()
            self.eventStartNewFrame.clear()
            self.eventProcessingCompleted.set()
        elif status == 4:
            # graph is finished all processing. Close app.
            self.eventFiniCompleted.set()
        return True
    

if __name__ == '__main__':
     
    import cv2
    import numpy as np


    logging.basicConfig(level=logging.INFO,
                format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    temcaGraph = TemcaGraph()
    temcaGraph.init()
    #temcaGraph.init('dummy')

    # get info about frame dimensions
{'fraction_non_alphanumeric': 0.10109141574425265, 'fraction_numerical': 0.007430915705549965, 'mean_word_length': 2.29171974522293, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7629696', 'n_tokens_mistral': 3934, 'n_tokens_neox': 3732, 'n_words': 1005}