emccd-detect 2.2.5__py3-none-any.whl → 2.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- emccd_detect/__init__.py +1 -1
- emccd_detect/emccd_detect.py +22 -5
- emccd_detect/nonlinearity.py +132 -0
- {emccd_detect-2.2.5.dist-info → emccd_detect-2.3.0.dist-info}/METADATA +3 -3
- {emccd_detect-2.2.5.dist-info → emccd_detect-2.3.0.dist-info}/RECORD +7 -6
- {emccd_detect-2.2.5.dist-info → emccd_detect-2.3.0.dist-info}/WHEEL +1 -1
- {emccd_detect-2.2.5.dist-info → emccd_detect-2.3.0.dist-info}/top_level.txt +0 -0
emccd_detect/__init__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
__version__ = '2.
|
2
|
+
__version__ = '2.3.0'
|
emccd_detect/emccd_detect.py
CHANGED
@@ -9,6 +9,7 @@ import numpy as np
|
|
9
9
|
|
10
10
|
from emccd_detect.cosmics import cosmic_hits, sat_tails
|
11
11
|
from emccd_detect.rand_em_gain import rand_em_gain
|
12
|
+
from emccd_detect.nonlinearity import apply_relgains
|
12
13
|
from emccd_detect.util.read_metadata_wrapper import MetadataWrapper
|
13
14
|
try:
|
14
15
|
from arcticpy import add_cti, CCD, ROE, Trap, TrapInstantCapture
|
@@ -260,7 +261,8 @@ class EMCCDDetectBase:
|
|
260
261
|
# Pass electrons through amplifier
|
261
262
|
amp_ev = self._amp(gain_counts)
|
262
263
|
|
263
|
-
# Pass amp electron volt counts through analog to digital converter
|
264
|
+
# Pass amp electron volt counts through analog to digital converter,
|
265
|
+
# applying nonlinearity if applicable
|
264
266
|
output_dn = self._adc(amp_ev)
|
265
267
|
|
266
268
|
return output_dn
|
@@ -400,10 +402,16 @@ class EMCCDDetectBase:
|
|
400
402
|
Analog to digital converter output (dn).
|
401
403
|
|
402
404
|
"""
|
403
|
-
# Convert from electron volts to dn
|
405
|
+
# Convert from electron volts to dn and apply nonlin if applicable
|
406
|
+
dn = amp_ev / self.eperdn
|
407
|
+
if hasattr(self, 'nonlin_path'):
|
408
|
+
if self.nonlin_path is not None:
|
409
|
+
nonlin_factors = apply_relgains(dn, self.em_gain,
|
410
|
+
self.nonlin_path)
|
411
|
+
dn *= nonlin_factors
|
404
412
|
dn_min = 0
|
405
413
|
dn_max = 2**self.nbits - 1
|
406
|
-
output_dn = np.clip(
|
414
|
+
output_dn = np.clip(dn, dn_min, dn_max).astype(np.uint64)
|
407
415
|
|
408
416
|
return output_dn
|
409
417
|
|
@@ -445,7 +453,13 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
445
453
|
Number of gain register elements. For eventually modeling partial CIC.
|
446
454
|
Defaults to 604.
|
447
455
|
meta_path : str
|
448
|
-
Full path of metadata.yaml.
|
456
|
+
Full path of metadata.yaml. If None, defaults to metadata.yaml in util
|
457
|
+
folder.
|
458
|
+
nonlin_path : str
|
459
|
+
Path of nonlinearity correction file. See doc string of
|
460
|
+
nonlinearity.apply_relgains for details on the required
|
461
|
+
format of the file. If None, defaults to no application of
|
462
|
+
nonlinearity.
|
449
463
|
|
450
464
|
"""
|
451
465
|
def __init__(
|
@@ -463,7 +477,8 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
463
477
|
eperdn=None,
|
464
478
|
nbits=14,
|
465
479
|
numel_gain_register=604,
|
466
|
-
meta_path=None
|
480
|
+
meta_path=None,
|
481
|
+
nonlin_path=None
|
467
482
|
):
|
468
483
|
# If no metadata file path specified, default to metadata.yaml in util
|
469
484
|
if meta_path is None:
|
@@ -480,6 +495,8 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
480
495
|
if eperdn is None:
|
481
496
|
eperdn = self.meta.eperdn
|
482
497
|
|
498
|
+
self.nonlin_path = nonlin_path
|
499
|
+
|
483
500
|
super().__init__(
|
484
501
|
em_gain=em_gain,
|
485
502
|
full_well_image=full_well_image,
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""Module for imposing nonlinearity (inverse of relative gains) for each
|
3
|
+
pixel of a frame.
|
4
|
+
|
5
|
+
Relative gain is dependent on both the detector gain and the dn count
|
6
|
+
value of a given pixel.
|
7
|
+
"""
|
8
|
+
|
9
|
+
import numpy as np
|
10
|
+
from scipy import interpolate
|
11
|
+
|
12
|
+
|
13
|
+
class NonlinException(Exception):
|
14
|
+
"""Exception class for nonlin module."""
|
15
|
+
|
16
|
+
|
17
|
+
def _parse_file(nonlin_path):
|
18
|
+
"""Get data from nonlinearity correction file."""
|
19
|
+
# Read nonlin csv
|
20
|
+
nonlin_raw = np.genfromtxt(nonlin_path, delimiter=',')
|
21
|
+
|
22
|
+
# File format checks
|
23
|
+
if nonlin_raw.ndim < 2 or nonlin_raw.shape[0] < 2 or \
|
24
|
+
nonlin_raw.shape[1] < 2:
|
25
|
+
raise NonlinException('Nonlin array must be at least 2x2 (room for x '
|
26
|
+
'and y axes and one data point)')
|
27
|
+
if not np.isnan(nonlin_raw[0, 0]):
|
28
|
+
raise NonlinException('First value of csv (upper left) must be set to '
|
29
|
+
'"nan"')
|
30
|
+
|
31
|
+
# Column headers are gains, row headers are dn counts
|
32
|
+
gain_ax = nonlin_raw[0, 1:]
|
33
|
+
count_ax = nonlin_raw[1:, 0]
|
34
|
+
# Array is relative gain values at a given dn count and gain
|
35
|
+
relgains = nonlin_raw[1:, 1:]
|
36
|
+
|
37
|
+
# Check for increasing axes
|
38
|
+
if np.any(np.diff(gain_ax) <= 0):
|
39
|
+
raise NonlinException('Gain axis (column headers) must be increasing')
|
40
|
+
if np.any(np.diff(count_ax) <= 0):
|
41
|
+
raise NonlinException('Counts axis (row headers) must be increasing')
|
42
|
+
# Check that curves (data in columns) contain or straddle 1.0
|
43
|
+
if (np.min(relgains, axis=0) > 1).any() or \
|
44
|
+
(np.max(relgains, axis=0) < 1).any():
|
45
|
+
raise NonlinException('Gain curves (array columns) must contain or '
|
46
|
+
'straddle a relative gain of 1.0')
|
47
|
+
|
48
|
+
return gain_ax, count_ax, relgains
|
49
|
+
|
50
|
+
|
51
|
+
def apply_relgains(frame, em_gain, nonlin_path):
|
52
|
+
"""For a given bias-subtracted flattened frame of dn counts,
|
53
|
+
return a same-size array of inverse relative gain values.
|
54
|
+
"Relative gain" here is the value
|
55
|
+
to correct for nonlinearity, the values from the input at nonlin_path, but
|
56
|
+
since this function applies nonlinearity, it returns the corresponding
|
57
|
+
inverse values.
|
58
|
+
|
59
|
+
The required format for the file specified at nonlin_path is as follows:
|
60
|
+
- CSV
|
61
|
+
- Minimum 2x2
|
62
|
+
- First value (top left) must be assigned to nan
|
63
|
+
- Row headers (dn counts) must be monotonically increasing
|
64
|
+
- Column headers (EM gains) must be monotonically increasing
|
65
|
+
- Data columns (relative gain curves) must straddle 1
|
66
|
+
|
67
|
+
For example:
|
68
|
+
|
69
|
+
[
|
70
|
+
[nan, 1, 10, 100, 1000 ],
|
71
|
+
[1, 0.900, 0.950, 0.989, 1.000],
|
72
|
+
[1000, 0.910, 0.960, 0.990, 1.010],
|
73
|
+
[2000, 0.950, 1.000, 1.010, 1.050],
|
74
|
+
[3000, 1.000, 1.001, 1.011, 1.060],
|
75
|
+
],
|
76
|
+
|
77
|
+
where the row headers [1, 1000, 2000, 3000] are dn counts, the column
|
78
|
+
headers [1, 10, 100, 1000] are EM gains, and the first data column
|
79
|
+
[0.900, 0.910, 0.950, 1.000] is the first of the four relative gain curves.
|
80
|
+
|
81
|
+
Parameters
|
82
|
+
----------
|
83
|
+
frame : array_like
|
84
|
+
Flattened array of dn count values.
|
85
|
+
em_gain : float
|
86
|
+
Detector EM gain.
|
87
|
+
nonlin_path : str
|
88
|
+
Full path of nonlinearity calibration csv.
|
89
|
+
|
90
|
+
Returns
|
91
|
+
-------
|
92
|
+
array_like
|
93
|
+
Flattened array of inverse relative gain values.
|
94
|
+
|
95
|
+
Notes
|
96
|
+
-----
|
97
|
+
This algorithm contains two interpolations:
|
98
|
+
|
99
|
+
- A 2d interpolation to find the relative gain curve for a given EM gain
|
100
|
+
- A 1d interpolation to find a relative gain value for each given dn
|
101
|
+
count value.
|
102
|
+
|
103
|
+
Both of these interpolations are linear, and both use their edge values as
|
104
|
+
constant extrapolations for out of bounds values.
|
105
|
+
|
106
|
+
"""
|
107
|
+
|
108
|
+
# Get file data
|
109
|
+
gain_ax, count_ax, relgains = _parse_file(nonlin_path)
|
110
|
+
|
111
|
+
# Create interpolation for em gain (x), counts (y), and relative gain (z).
|
112
|
+
# Note that this defaults to using the edge values as fill_value for
|
113
|
+
# out of bounds values (same as specified below in interp1d)
|
114
|
+
f = interpolate.RectBivariateSpline(gain_ax,
|
115
|
+
count_ax,
|
116
|
+
relgains.T,
|
117
|
+
kx=1,
|
118
|
+
ky=1,
|
119
|
+
)
|
120
|
+
# Get the relative gain curve for the given gain value
|
121
|
+
relgain_curve = f(em_gain, count_ax)[0]
|
122
|
+
|
123
|
+
# Create interpolation for dn counts (x) and relative gains (y). For
|
124
|
+
# out of bounds values use edge values
|
125
|
+
ff = interpolate.interp1d(count_ax, relgain_curve, kind='linear',
|
126
|
+
bounds_error=False,
|
127
|
+
fill_value=(relgain_curve[0], relgain_curve[-1]))
|
128
|
+
# For each dn count, find the inverse of the relative gain since
|
129
|
+
# we are applying nonlinearity instead of correcting for it
|
130
|
+
counts_flat = 1/ff(frame)
|
131
|
+
|
132
|
+
return counts_flat
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: emccd_detect
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.3.0
|
4
4
|
Summary: EMCCD detector image simulation
|
5
5
|
Home-page: https://github.jpl.nasa.gov/WFIRST-CGI/emccd_detect
|
6
6
|
Author: Bijan Nemati, Sam Miller, Kevin Ludwick
|
@@ -22,12 +22,12 @@ Requires-Dist: pyyaml
|
|
22
22
|
|
23
23
|
# EMCCD Detect
|
24
24
|
|
25
|
-
Given an input fluxmap, emccd_detect will return a simulated EMCCD detector image.
|
25
|
+
Given an input fluxmap, emccd_detect will return a simulated EMCCD detector image. Website: (<https://github.com/roman-corgi/emccd_detect/tree/master/emccd_detect>)
|
26
26
|
|
27
27
|
|
28
28
|
# Version
|
29
29
|
|
30
|
-
The latest version of emccd\_detect is 2.
|
30
|
+
The latest version of emccd\_detect is 2.3.0.
|
31
31
|
|
32
32
|
|
33
33
|
## Getting Started
|
@@ -1,12 +1,13 @@
|
|
1
|
-
emccd_detect/__init__.py,sha256=
|
1
|
+
emccd_detect/__init__.py,sha256=p-NmfUlr25lTkWkeCxbgt34N36FhFb8AqPQG7WvWx8E,45
|
2
2
|
emccd_detect/cosmics.py,sha256=wRE47QOB3fwxkH5PHTeoyLjJ0fgJki6Z8hLDPx2h3SQ,3991
|
3
|
-
emccd_detect/emccd_detect.py,sha256=
|
3
|
+
emccd_detect/emccd_detect.py,sha256=Ige6TKmeR4xHW2Jd_XOnG-NMHNodS_nr1dgGv0x6B_k,23136
|
4
|
+
emccd_detect/nonlinearity.py,sha256=sWsYXbH5Ck2DSUntC0zbXlmsTzYw73T27tIKs41nApQ,4822
|
4
5
|
emccd_detect/rand_em_gain.py,sha256=3eF9T7PNYFZT0coGZwBmNTYz6B9pj2lXxTR8ROG6_7Q,6297
|
5
6
|
emccd_detect/util/__init__.py,sha256=iwhKnzeBJLKxpRVjvzwiRE63_zNpIBfaKLITauVph-0,24
|
6
7
|
emccd_detect/util/metadata.yaml,sha256=hcKTg4kMy12dfbCmmvZeKEqjeUA3BYiAcZc5vZpc3bE,1149
|
7
8
|
emccd_detect/util/read_metadata.py,sha256=r511ENJ6zbIvLDWiVic7KsVXYrBphSdTKUQbuwocjLs,2764
|
8
9
|
emccd_detect/util/read_metadata_wrapper.py,sha256=oBh2KpJ-uLTSIY_hPzw8sNIcJ6MENBSf38ks8OaFOSQ,5473
|
9
|
-
emccd_detect-2.
|
10
|
-
emccd_detect-2.
|
11
|
-
emccd_detect-2.
|
12
|
-
emccd_detect-2.
|
10
|
+
emccd_detect-2.3.0.dist-info/METADATA,sha256=VDjFt5KKwFd8sM1XnF9M2DStCHWIkQ54zq6ia4P-0E8,2391
|
11
|
+
emccd_detect-2.3.0.dist-info/WHEEL,sha256=uCRv0ZEik_232NlR4YDw4Pv3Ajt5bKvMH13NUU7hFuI,91
|
12
|
+
emccd_detect-2.3.0.dist-info/top_level.txt,sha256=V0qxOcGf8TowSJXnTxWEMuK9BBsySwhtKNitfdokD0A,13
|
13
|
+
emccd_detect-2.3.0.dist-info/RECORD,,
|
File without changes
|