Source code for emva1288.camera.points_generator

import numpy as np
from collections import OrderedDict


[docs]class PointsGenerator: """Class that generates a dictionary of operation points for an emva test. The points are stored in the :attr:`points` attribute as a dictionary. The points are ordered if they are a 'spatial' or 'temporal' operation point. Under each keys there is a dictionary whose keys are the different exposure times and their values are the list of radiances under which the camera is illuminated. """
[docs] def __init__(self, cam, exposure_min=None, exposure_max=None, exposure_fixed=None, radiance_min=None, radiance_max=None, gain=None, blackref=None, steps=100): """Point generator init method. Parameters ---------- cam : The camera object that will be taking the images. exposure_min : float, optional The minimal exposure time (in ns). exposure_max : float, optional The maximal exposure time (in ns). exposure_fixed : float, optional By default, the points given are for an exposure time variation test (if this is None). If a value is given to this kwarg, this will be the camera's exposure time (in ns) at which the operation points will be set for an illumination variation test. radiance_min : float, optional The minimal radiance (in W/cm^2/sr). If None, a value above dark illumination will be automatically chosen. radiance_max : float, optional The maximal radiance (in W/cm^2/sr). If None, the maximal radiation will be taken as the saturation radiation for the exposition time given in the exposure_fixed kwarg. gain : float, optional The camera's gain at which we want the test to run. blackref : float, optional The camera's blackoffset at which we want the test to run. steps : int, optional The number of points in the test. """ self._cam = cam self._steps = steps self._exposure_min = exposure_min or self._cam.exposure_min self._exposure_max = exposure_max or self._cam.exposure_max self._exposure = exposure_fixed self._radiance_min = radiance_min self._radiance_max = radiance_max self._gain = gain or self._cam.K self._blackref = blackref or self._cam.blackoffset if self._exposure is None: # Get radiance for saturation at maximal exposure time # Only if it is for an exposure time variation test self._cam.exposure = self._exposure_max self._radiance = self._cam.get_radiance_for() else: # get radiances for radiation variation self._cam.exposure = self._exposure self._cam.K = self._gain self._cam.blackoffset = self._blackref m = self._cam.grab(0).mean() target = (self._cam.img_max - m) / self._steps + m self._radiance_min = self._cam.get_radiance_for(mean=target) self._radiance_max = self._cam.get_radiance_for() # By default, an exposure time variation data points # If exposure fixed is given, it is photons variation self._points = self._get_points()
def _get_points(self): spatial = OrderedDict() temporal = OrderedDict() rad = np.zeros((self._cam._height, self._cam._width, len(self._cam.qe.w))) if self._exposure is None: # Exposure time variation # round to only have one decimal exposures = np.round(np.linspace(self._exposure_min, self._exposure_max, self._steps), 1) # only one radiance radiances = [self._radiance, rad] # Main loop to compute points for n, texp in enumerate(exposures): if self._is_point_spatial(n): spatial[texp] = radiances temporal[texp] = radiances else: # Photons variations # only one exposure time rad_i = np.ones((self._cam._height, self._cam._width, len(self._cam.qe.w))) factors = np.linspace(self._radiance_min.mean(), self._radiance_max.mean(), self._steps) radiances = [rad_i * factor for factor in factors] # round to only have one decimal self._exposure = round(self._exposure) radiances.append(rad) spatial[self._exposure] = [radiances[self._steps // 2], rad] temporal[self._exposure] = radiances return {'spatial': spatial, 'temporal': temporal} @property def points(self): """The operation points.""" return self._points def _is_point_spatial(self, n): """Checks if a spatial test must be done at this point. Spatial test are executed at mid run for both dark and bright tests. """ middle = self._steps // 2 if n in (middle, self._steps + middle): return True return False