Source code for emva1288.process.loader

# -*- coding: utf-8 -*-
# Copyright (c) 2014 The EMVA1288 Authors. All rights reserved.
# Use of this source code is governed by a GNU GENERAL PUBLIC LICENSE that can
# be found in the LICENSE file.

"""Load image data
This class takes a dictionary (product of parser.ParseEmvaDescriptorFile).
Load the related images and reduce it's data to the minimum possible,
preserving all relevant image data in as integers
"""

import os
import numpy as np
from . import routines
import logging


[docs]class LoadImageData(object): """Using an info dictionary, load the images and fill data with the relevant information. """
[docs] def __init__(self, images, path='', loglevel=logging.INFO, fload=routines.load_image, fload_args=[], fload_kwargs={}): """Loader init method. Uses a :class:`python:logging.Logger` object to print infos for the user. In the initialization, it :meth:`loads <_load_data>` the infos from the images into the data dictionary. Parameters ---------- images : dict The :attr:`~emva1288.process.parser.ParseEmvaDescriptorFile.images` attribute of a :class:`~emva1288.process.parser.ParseEmvaDescriptorFile` object that have parsed the images of a descriptor file. path : str, optional The path to the directory containing the images. loglevel : int, optional The information level for the :class:`~python:logging.Logger`. fload : func. optional The function that will load the images (one at a time). fload_args : list, optional The list of args for the fload function. fload_kwargs : dict, optional The kwargs dictionary for the fload function. """ self.data = {'temporal': {}, 'spatial': {}} self._fload = fload self._fload_args = fload_args self._fload_kwargs = fload_kwargs self._shape = set() logging.basicConfig() self.log = logging.getLogger('Loader') self.log.setLevel(loglevel) self._path = path # load the images self._load_data(images)
def _load_data(self, images): """Using the information in images dict fill self.data when loading the images and fills the temporal and spatial dicts """ # iterate over the kind for kind in ('temporal', 'spatial'): exposures = set(images[kind].keys()) # iterate over the exposure times for each kind for exposure in exposures: # for this exposure time, get the list of photons counts photon_counts = list(images[kind][exposure].keys()) if 0.0 not in photon_counts: # Every exposure time should have at least one dark # image with a 0 photon count. raise ValueError('Every exposure must have a 0.0 photons' ' for dark information') if len(photon_counts) < 2: # Every exposure time should have at least one dark image # and one bright image. raise ValueError('All exposure must have at least 2 points' ' one dark and one bright') # Iterate over the images for this exposure time and this # photon count for photons, fnames in images[kind][exposure].items(): # get the image data data_imgs = self._get_imgs_data(fnames, kind) # fill data dict self.data[kind].setdefault(exposure, {}) self.data[kind][exposure][photons] = data_imgs shape = self._shape.pop() self.data['height'] = shape[0] self.data['width'] = shape[1] def _get_imgs_data(self, fnames, kind): """Returns the desired image data This depends on the kind of data """ # Load a list containing the images arr_imgs = self._load_imgs(fnames) # Get the sum and the pseudo-variance of this list of images imgs = routines.get_int_imgs(arr_imgs) # For spatial we only want the sum and pseudo-var of the images if kind == 'spatial': return imgs # For temporal, we only want the basic statistics (we don't need # the whole sum and pvar images) d = {} d['sum'] = np.sum(imgs['sum']) # sum of the sum of images d['pvar'] = np.sum(imgs['pvar']) # sum of the pvar image d['dmean'] = imgs['dmean'] # sum of the dmean image return d def _load_imgs(self, fnames): """For a list of path to images, load and append them to a returned list. """ imgs = [] # Iterate over all images for fname in fnames: # Get the path to the specific image. filename = os.path.join(self._path, fname) self.log.debug('Loading ' + fname) if not os.path.isfile(filename): # If the path is not good, raise an error. raise IOError('Not such file: ' + filename) # If path is good, load the image using the fload function img = self._fload(filename, *self._fload_args, **self._fload_kwargs) # Append the loaded image to the list imgs.append(img) # Add the image shape to the set self._shape.add(img.shape) if len(self._shape) > 1: # pragma: no cover # If the shape set contains more than 1 element, this means # not all images have the same shape. raise ValueError('All images must have the same shape') return imgs