Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions emva1288/process/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ def __init__(self,
self.data = {}
self.data['temporal'] = self._get_temporal(data['temporal'])
self.data['spatial'] = self._get_spatial(data['spatial'])
self.data['darkcurrent'] =self._get_temporal(data['darkcurrent'], True)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
self.data['darkcurrent'] =self._get_temporal(data['darkcurrent'], True)
self.data['darkcurrent'] = self._get_temporal(data['darkcurrent'], True)

print()

def _get_temporal(self, data):
def _get_temporal(self, data, dark_only=False):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't mind adding dark_only to the Parameters section in _get_temporal

"""Fill the temporal dict, with the stuff that we need.
Compute the averages and variances from the sums (sum and pvar)

Expand Down Expand Up @@ -84,8 +86,10 @@ def _get_temporal(self, data):
time and photon count,
*'u_ydark'*: the array of the mean digital dark value
for each exposure time
and *'s2_ydark'*: the
array of the digital dark value variance for each exposure time.
*'s2_ydark'*: the
array of the digital dark value variance for each exposure time
and *'diff_u_y'*: the difference of the mean values of the images

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can keep s2_ydark and diff_u_y separated in the doc string here

Suggested change
and *'diff_u_y'*: the difference of the mean values of the images
*'s2_ydark'*: the array of the digital dark value variance
for each exposure time.
*'diff_u_y'*: the difference of the mean values of the images
for each exposure time.

for each exposure time.

Raises
------
Expand All @@ -106,6 +110,7 @@ def _get_temporal(self, data):
s2_y = []
u_ydark = []
s2_ydark = []
diff_u_y = []

for t in exposures:
# photons is a list of photon counts
Expand All @@ -115,7 +120,7 @@ def _get_temporal(self, data):
if 0.0 not in photons:
raise ValueError('Every exposure point must have a 0.0 photon')

if len(photons) < 2:
if len(photons) < 2 and not dark_only:
raise ValueError('There must be at least one bright photon')

# get data for dark image
Expand All @@ -129,13 +134,15 @@ def _get_temporal(self, data):
d = self._get_temporal_data(data[t][p])
u_y.append(d['mean'])
s2_y.append(d['var'] - d['dmean'])
diff_u_y.append(data[t][p]['dmean']) # we need to use the raw difference here

# Append all data to temporal dict
temporal['u_p'] = np.asarray(u_p)
temporal['u_y'] = np.asarray(u_y)
temporal['s2_y'] = np.asarray(s2_y)
temporal['u_ydark'] = np.asarray(u_ydark)
temporal['s2_ydark'] = np.asarray(s2_ydark)
temporal['diff_u_y'] = np.asarray(diff_u_y)

# In case we have only one exposure, we need arrays with the
# same length as the up
Expand Down
7 changes: 4 additions & 3 deletions emva1288/process/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def __init__(self,
fload_kwargs : dict, optional
The kwargs dictionary for the fload function.
"""
self.data = {'temporal': {}, 'spatial': {}}
self.data = {'temporal': {}, 'spatial': {}, 'darkcurrent': {}}
self._fload = fload
self._fload_args = fload_args
self._fload_kwargs = fload_kwargs
Expand All @@ -72,7 +72,7 @@ def _load_data(self, images):
the images and fills the temporal and spatial dicts
"""
# iterate over the kind
for kind in ('temporal', 'spatial'):
for kind in ('temporal', 'spatial', 'darkcurrent'):
exposures = set(images[kind].keys())

# iterate over the exposure times for each kind
Expand All @@ -85,9 +85,10 @@ def _load_data(self, images):
# image with a 0 photon count.
raise ValueError('Every exposure must have a 0.0 photons'
' for dark information')
if len(photon_counts) < 2:
if len(photon_counts) < 2 and kind != "darkcurrent":
# Every exposure time should have at least one dark image
# and one bright image.
# NOTE: We can allow only dark values for dark current measurement
raise ValueError('All exposure must have at least 2 points'
' one dark and one bright')

Expand Down
20 changes: 12 additions & 8 deletions emva1288/process/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def __init__(self, filename, path=None, loglevel=logging.INFO):
self.format = {} # bits, witdth, height
self.version = None
self.images = {'temporal': {},
'darkcurrent': {},
'spatial': {}}

logging.basicConfig()
Expand Down Expand Up @@ -89,28 +90,31 @@ def _get_images_filenames(self):

return fnames

def _get_kind(self, fnames):
def _get_kind(self, fnames, img_type=""):
"""
Guess what kind of data based on the number of images
Temporal = 2 images for each measurement point
Spatial = >2 images for each measurement point
"""
L = len(fnames)
if L == 2:
kind = 'temporal'
if img_type == "dc":
kind = 'darkcurrent'
else:
kind = 'temporal'
else:
kind = 'spatial'

return kind

def _add_pcount(self, exposure, photons, fnames):
"""Add images to a given exposure/phton
def _add_pcount(self, exposure, photons, fnames, img_type=""):
"""Add images to a given exposure/photon

For a given exposure and photon count
add the appropiate image filenames to the self.images dict
"""
# is it temporal or spatial data
kind = self._get_kind(fnames)
kind = self._get_kind(fnames, img_type)
# create the exposure time dictionary for this exposure time
# if it is not already existing
self.images[kind].setdefault(exposure, {})
Expand Down Expand Up @@ -145,7 +149,7 @@ def _fill_info(self):
# b exposureTime(ns) numberPhotons (bright image)
# i relativePathToTheImage
# d exposureTime(ns) (dark image)

if l[0] == 'v':
# if line starts with 'v', this is the version
self.version = l[1]
Expand Down Expand Up @@ -189,7 +193,7 @@ def _fill_info(self):

continue

if l[0] == 'd':
if l[0] in ['d', 'dc']:
# For lines that starts with d, there is always 2 elements
# d + exposureTime (dark images)
if len(l) != 2: # pragma: no cover
Expand All @@ -201,7 +205,7 @@ def _fill_info(self):
# For this exposure, get all the corresponding images
fnames = self._get_images_filenames()
# Add the images path to the images dict.
self._add_pcount(exposure, float(0.0), fnames)
self._add_pcount(exposure, float(0.0), fnames, l[0])

continue

Expand Down
93 changes: 93 additions & 0 deletions emva1288/process/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,93 @@ def plot(self, test):
self.set_legend(ax)


class PlotUyDarkCurrent(Emva1288Plot):
name = 'Dark Current From Mean'
xlabel = 'exposure time [ns]'
ylabel = r'$\mu_{y.dark}$ [DN]'

def plot(self, test):
ax = self.ax

if len(test.darkcurrent['texp']) > 2:
data = test.darkcurrent
else:
data = test.temporal

if test.dark_current_fit_mean() is not np.nan:
X = data['texp']

ax.plot(X,
data['u_ydark'],
marker='o',
markersize=5,
Comment on lines +215 to +216

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This marker style makes it a little difficult to track deviation from fit, I think sticking to default plotting params for the data is fine

Suggested change
marker='o',
markersize=5,

image

label='Data',
gid='%d:data' % test.id)
ax.plot(X,
test.dark_current_fit_mean()['fit_slope'] *
X + test.dark_current_fit_mean()['fit_offset'],
linestyle='--',
label='Fit',
gid='%d:fit' % test.id)
ax.ticklabel_format(axis='x', style='sci', scilimits=(1, 4))
self.set_legend(ax)

class PlotVaryDarkCurrent(Emva1288Plot):
name = 'Dark Current From Variance'
xlabel = 'exposure time [ns]'
ylabel = r'$\sigma^2_{y.dark}$ [DN$^2$]'


def plot(self, test):
ax = self.ax

if len(test.darkcurrent['texp']) > 2:
data = test.darkcurrent
else:
data = test.temporal

if test.dark_current_fit_var() is not np.nan:
X = data['texp']

ax.plot(X,
data['s2_ydark'],
marker='o',
markersize=5,
Comment on lines +247 to +248

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same idea as above

Suggested change
marker='o',
markersize=5,

image

label='Data',
gid='%d:data' % test.id)
ax.plot(X,
test.dark_current_fit_var()['fit_slope'] *
X + test.dark_current_fit_var()['fit_offset'],
linestyle='--',
label='Fit',
gid='%d:fit' % test.id)
ax.ticklabel_format(axis='x', style='sci', scilimits=(1, 4))
self.set_legend(ax)


class PlotStabilityCheck(Emva1288Plot):
''' Create the stability check plot '''
name = 'Stability Check'
xlabel = r'gray value [DN]'
ylabel = r'difference/std gray value [DN]'

def plot(self, test):
ax = self.ax

X = test.temporal['u_y'] - test.temporal['u_ydark']
Y1 = np.sqrt(test.temporal['s2_y'])
Y2 = test.temporal['diff_u_y']
ax.plot(X, Y1,
label='Std',
gid='%d:std' % test.id)
ax.plot(X, Y2,
label='Difference',
marker='.',
ls=' ',
gid='%d:difference' % test.id)
self.set_legend(ax)


class PlotPTC(Emva1288Plot):
'''Create Photon Transfer plot'''

Expand Down Expand Up @@ -792,10 +879,13 @@ def rearrange(self):

EVMA1288plots = [PlotPTC,
PlotSNR,
PlotStabilityCheck,
PlotSensitivity,
PlotUyDark,
PlotLinearity,
PlotDeviationLinearity,
PlotUyDarkCurrent,
PlotVaryDarkCurrent,
PlotHorizontalSpectrogramPRNU,
PlotHorizontalSpectrogramDSNU,
PlotVerticalSpectrogramPRNU,
Expand All @@ -812,10 +902,13 @@ def rearrange(self):

- :class:`~emva1288.process.plotting.PlotPTC`
- :class:`~emva1288.process.plotting.PlotSNR`
- :class:`~emva1288.process.plotting.PlotStabilityCheck`
- :class:`~emva1288.process.plotting.PlotSensitivity`
- :class:`~emva1288.process.plotting.PlotUyDark`
- :class:`~emva1288.process.plotting.PlotLinearity`
- :class:`~emva1288.process.plotting.PlotDeviationLinearity`
- :Class:`~emva1288.process.plotting.PlotUyDarkCurrent`
- :Class:`~emva1288.process.plotting.PlotVaryDarkCurrent`
- :class:`~emva1288.process.plotting.PlotHorizontalSpectrogramPRNU`
- :class:`~emva1288.process.plotting.PlotHorizontalSpectrogramDSNU`
- :class:`~emva1288.process.plotting.PlotVerticalSpectrogramPRNU`
Expand Down
Loading