Beispiel #1
0
def liveview_acquire(datapath, config_filename, writeToDisk=False):
    '''Aquire images from the SilCam

    Args:
       datapath              (str)          :  Path to the image storage
       config_filename=None  (str)          :  Camera config file
       writeToDisk=True      (Bool)         :  True will enable writing of raw data to disc
                                               False will disable writing of raw data to disc
       gui=None          (Class object)     :  Queue used to pass information between process thread and GUI
                                               initialised in ProcThread within guicals.py
    '''

    #Load the configuration, create settings object
    settings = PySilcamSettings(config_filename)

    #Print configuration to screen
    print('---- CONFIGURATION ----\n')
    settings.config.write(sys.stdout)
    print('-----------------------\n')

    if (writeToDisk):
        # Copy config file
        configFile2Copy = datetime.datetime.now().strftime(
            'D%Y%m%dT%H%M%S.%f') + os.path.basename(config_filename)
        copyfile(config_filename, os.path.join(datapath, configFile2Copy))

    configure_logger(settings.General)

    # update path_length
    updatePathLength(settings, logger)

    acq = Acquire(USE_PYMBA=True)  # ini class
    t1 = time.time()

    aqgen = acq.get_generator(datapath,
                              camera_config_file=config_filename,
                              writeToDisk=writeToDisk)

    for i, (timestamp, imraw) in enumerate(aqgen):
        t2 = time.time()
        aq_freq = np.round(1.0 / (t2 - t1), 1)
        requested_freq = settings.Camera.acquisitionframerateabs
        rest_time = (1 / requested_freq) - (1 / aq_freq)
        rest_time = np.max([rest_time, 0.])
        actual_aq_freq = 1 / (1 / aq_freq + rest_time)
        logger.info('Image {0} acquired at frequency {1:.1f} Hz'.format(
            i, actual_aq_freq))
        t1 = time.time()

        yield timestamp, imraw
Beispiel #2
0
def silcam_process(config_filename,
                   datapath,
                   multiProcess=True,
                   realtime=False,
                   discWrite=False,
                   nbImages=None,
                   gui=None,
                   overwriteSTATS=True):
    '''Run processing of SilCam images

    Args:
      config_filename   (str)               :  The filename (including path) of the config.ini file
      datapath          (str)               :  Path to the data directory
      multiProcess=True (bool)              :  If True, multiprocessing is used
      realtime=False    (bool)              :  If True, a faster but less accurate methods is used for segmentation and rts stats become active
      discWrite=False   (bool)              :  True will enable writing of raw data to disc
                                               False will disable writing of raw data to disc
      nbImages=None     (int)               :  Number of images to skip
      gui=None          (Class object)      :  Queue used to pass information between process thread and GUI
                                               initialised in ProcThread within guicals.py
    '''
    print(config_filename)

    print('')
    # ---- SETUP ----

    # Load the configuration, create settings object
    settings = PySilcamSettings(config_filename)

    # Print configuration to screen
    print('---- CONFIGURATION ----\n')
    settings.config.write(sys.stdout)
    print('-----------------------\n')

    # Configure logging
    configure_logger(settings.General)
    logger = logging.getLogger(__name__ + '.silcam_process')

    logger.info('Processing path: ' + datapath)

    if realtime:
        if discWrite:
            # copy config file into data path
            configFile2Copy = datetime.datetime.now().strftime(
                'D%Y%m%dT%H%M%S.%f') + os.path.basename(config_filename)
            copyfile(config_filename, os.path.join(datapath, configFile2Copy))

        # update path_length
        updatePathLength(settings, logger)

    # make datafilename autogenerated for easier batch processing
    if (not os.path.isdir(settings.General.datafile)):
        logger.info('Folder ' + settings.General.datafile +
                    ' was not found and is created')
        os.mkdir(settings.General.datafile)

    procfoldername = os.path.split(datapath)[-1]
    datafilename = os.path.join(settings.General.datafile, procfoldername)
    logger.info('output stats to: ' + datafilename)

    adminSTATS(logger, settings, overwriteSTATS, datafilename, datapath)

    # Initialize the image acquisition generator
    if 'REALTIME_DISC' in os.environ.keys():
        print('acq = Acquire(USE_PYMBA=False)')
        aq = Acquire(USE_PYMBA=False)
    else:
        aq = Acquire(USE_PYMBA=realtime)
    aqgen = aq.get_generator(datapath,
                             writeToDisk=discWrite,
                             camera_config_file=config_filename)

    # Get number of images to use for background correction from config
    print('* Initializing background image handler')
    bggen = backgrounder(
        settings.Background.num_images,
        aqgen,
        bad_lighting_limit=settings.Process.bad_lighting_limit,
        real_time_stats=settings.Process.real_time_stats)

    # Create export directory if needed
    if settings.ExportParticles.export_images:
        if (not os.path.isdir(settings.ExportParticles.outputpath)):
            logger.info('Export folder ' +
                        settings.ExportParticles.outputpath +
                        ' was not found and is created')
            os.mkdir(settings.ExportParticles.outputpath)

    # ---- END SETUP ----

    # ---- RUN PROCESSING ----

    # If only one core is available, no multiprocessing will be done
    multiProcess = multiProcess and (multiprocessing.cpu_count() > 1)

    print('* Commencing image acquisition and processing')

    # initialise realtime stats class regardless of whether it is used later
    rts = scog.rt_stats(settings)

    if (multiProcess):
        proc_list = []
        mem = psutil.virtual_memory()
        memAvailableMb = mem.available >> 20
        distributor_q_size = np.min([
            int(memAvailableMb / 2 * 1 / 15),
            np.copy(multiprocessing.cpu_count() * 4)
        ])

        logger.debug('setting up processing queues')
        inputQueue, outputQueue = defineQueues(realtime, distributor_q_size)

        logger.debug('setting up processing distributor')
        distributor(inputQueue, outputQueue, config_filename, proc_list, gui)

        # iterate on the bggen generator to obtain images
        logger.debug('Starting acquisition loop')
        t2 = time.time()
        for i, (timestamp, imc, imraw) in enumerate(bggen):
            t1 = np.copy(t2)
            t2 = time.time()
            print(t2 - t1, 'Acquisition loop time')
            logger.debug('Corrected image ' + str(timestamp) +
                         ' acquired from backgrounder')

            # handle errors if the loop function fails for any reason
            if (nbImages != None):
                if (nbImages <= i):
                    break

            logger.debug('Adding image to processing queue: ' + str(timestamp))
            addToQueue(
                realtime, inputQueue, i, timestamp, imc
            )  # the tuple (i, timestamp, imc) is added to the inputQueue
            logger.debug('Processing queue updated')

            # write the images that are available for the moment into the csv file
            logger.debug('Running collector')
            collector(inputQueue,
                      outputQueue,
                      datafilename,
                      proc_list,
                      False,
                      settings,
                      rts=rts)
            logger.debug('Data collected')

            if not gui == None:
                logger.debug('Putting data on GUI Queue')
                while (gui.qsize() > 0):
                    try:
                        gui.get_nowait()
                        time.sleep(0.001)
                    except:
                        continue
                # try:
                rtdict = dict()
                rtdict = {
                    'dias': rts.dias,
                    'vd_oil': rts.vd_oil,
                    'vd_gas': rts.vd_gas,
                    'oil_d50': rts.oil_d50,
                    'gas_d50': rts.gas_d50,
                    'saturation': rts.saturation
                }
                gui.put_nowait((timestamp, imc, imraw, rtdict))
                logger.debug('GUI queue updated')

            if 'REALTIME_DISC' in os.environ.keys():
                scog.realtime_summary(datafilename + '-STATS.csv',
                                      config_filename)

        logger.debug('Acquisition loop completed')
        if (not realtime):
            logger.debug('Halting processes')
            for p in proc_list:
                inputQueue.put(None)

        # some images might still be waiting to be written to the csv file
        logger.debug('Running collector on left over data')
        collector(inputQueue,
                  outputQueue,
                  datafilename,
                  proc_list,
                  True,
                  settings,
                  rts=rts)
        logger.debug('All data collected')

        for p in proc_list:
            p.join()
            logger.info('%s.exitcode = %s' % (p.name, p.exitcode))

    else:  # no multiprocessing
        # load the model for particle classification and keep it for later
        nnmodel = []
        nnmodel, class_labels = sccl.load_model(
            model_path=settings.NNClassify.model_path)

        # iterate on the bggen generator to obtain images
        for i, (timestamp, imc, imraw) in enumerate(bggen):
            # handle errors if the loop function fails for any reason
            if (nbImages != None):
                if (nbImages <= i):
                    break

            image = (i, timestamp, imc)
            # one single image is processed at a time
            stats_all = processImage(nnmodel, class_labels, image, settings,
                                     logger, gui)

            if (not stats_all is None):  # if frame processed
                # write the image into the csv file
                writeCSV(datafilename, stats_all)
                if 'REALTIME_DISC' in os.environ.keys():
                    scog.realtime_summary(datafilename + '-STATS.csv',
                                          config_filename)

            if not gui == None:
                collect_rts(settings, rts, stats_all)
                logger.debug('Putting data on GUI Queue')
                while (gui.qsize() > 0):
                    try:
                        gui.get_nowait()
                        time.sleep(0.001)
                    except:
                        continue
                # try:
                rtdict = dict()
                rtdict = {
                    'dias': rts.dias,
                    'vd_oil': rts.vd_oil,
                    'vd_gas': rts.vd_gas,
                    'oil_d50': rts.oil_d50,
                    'gas_d50': rts.gas_d50,
                    'saturation': rts.saturation
                }
                gui.put_nowait((timestamp, imc, imraw, rtdict))
                logger.debug('GUI queue updated')

    print('PROCESSING COMPLETE.')
Beispiel #3
0
def silcam_acquire(datapath, config_filename, writeToDisk=True, gui=None):
    '''Aquire images from the SilCam

    Args:
       datapath              (str)          :  Path to the image storage
       config_filename=None  (str)          :  Camera config file
       writeToDisk=True      (Bool)         :  True will enable writing of raw data to disc
                                               False will disable writing of raw data to disc
       gui=None          (Class object)     :  Queue used to pass information between process thread and GUI
                                               initialised in ProcThread within guicals.py
    '''

    # Load the configuration, create settings object
    settings = PySilcamSettings(config_filename)

    # Print configuration to screen
    print('---- CONFIGURATION ----\n')
    settings.config.write(sys.stdout)
    print('-----------------------\n')

    if (writeToDisk):
        # Copy config file
        configFile2Copy = datetime.datetime.now().strftime(
            'D%Y%m%dT%H%M%S.%f') + os.path.basename(config_filename)
        copyfile(config_filename, os.path.join(datapath, configFile2Copy))

    configure_logger(settings.General)
    logger = logging.getLogger(__name__ + '.silcam_acquire')

    # update path_length
    updatePathLength(settings, logger)

    acq = Acquire(USE_PYMBA=True)  # ini class
    t1 = time.time()

    aqgen = acq.get_generator(datapath,
                              camera_config_file=config_filename,
                              writeToDisk=writeToDisk)

    for i, (timestamp, imraw) in enumerate(aqgen):
        t2 = time.time()
        aq_freq = np.round(1.0 / (t2 - t1), 1)
        requested_freq = settings.Camera.acquisitionframerateabs
        rest_time = (1 / requested_freq) - (1 / aq_freq)
        rest_time = np.max([rest_time, 0.])
        time.sleep(rest_time)
        actual_aq_freq = 1 / (1 / aq_freq + rest_time)
        print('Image {0} acquired at frequency {1:.1f} Hz'.format(
            i, actual_aq_freq))
        t1 = time.time()

        if not gui == None:
            while (gui.qsize() > 0):
                try:
                    gui.get_nowait()
                    time.sleep(0.001)
                except:
                    continue
            # try:
            rtdict = dict()
            rtdict = {
                'dias': 0,
                'vd_oil': 0,
                'vd_gas': 0,
                'oil_d50': 0,
                'gas_d50': 0,
                'saturation': 0
            }
            gui.put_nowait((timestamp, imraw, imraw, rtdict))