emccd-detect 2.4.0__py3-none-any.whl → 2.5.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 +82 -17
- emccd_detect/util/metadata.yaml +1 -8
- emccd_detect/util/read_metadata.py +0 -21
- emccd_detect/util/read_metadata_wrapper.py +0 -14
- {emccd_detect-2.4.0.dist-info → emccd_detect-2.5.0.dist-info}/METADATA +9 -9
- emccd_detect-2.5.0.dist-info/RECORD +14 -0
- {emccd_detect-2.4.0.dist-info → emccd_detect-2.5.0.dist-info}/WHEEL +1 -1
- emccd_detect-2.5.0.dist-info/licenses/LICENSE.txt +21 -0
- emccd_detect-2.4.0.dist-info/RECORD +0 -13
- {emccd_detect-2.4.0.dist-info → emccd_detect-2.5.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.5.0'
|
emccd_detect/emccd_detect.py
CHANGED
@@ -6,6 +6,7 @@ import warnings
|
|
6
6
|
from pathlib import Path
|
7
7
|
|
8
8
|
import numpy as np
|
9
|
+
from astropy.io import fits
|
9
10
|
|
10
11
|
from emccd_detect.cosmics import cosmic_hits, sat_tails
|
11
12
|
from emccd_detect.rand_em_gain import rand_em_gain
|
@@ -54,7 +55,12 @@ class EMCCDDetectBase:
|
|
54
55
|
inclusive.
|
55
56
|
numel_gain_register : int
|
56
57
|
Number of gain register elements. For eventually modeling partial CIC.
|
57
|
-
|
58
|
+
row_read_time : float
|
59
|
+
Time in seconds for each row to move into the first register (same as
|
60
|
+
the time for each row to be clocked toward the register). This is used
|
61
|
+
to simulate smear on the image due to clocking during the exposure to
|
62
|
+
light. Especially useful for shutterless EMCCDs. If 0, no smear is
|
63
|
+
simulated.
|
58
64
|
"""
|
59
65
|
def __init__(
|
60
66
|
self,
|
@@ -70,7 +76,8 @@ class EMCCDDetectBase:
|
|
70
76
|
pixel_pitch,
|
71
77
|
eperdn,
|
72
78
|
nbits,
|
73
|
-
numel_gain_register
|
79
|
+
numel_gain_register,
|
80
|
+
row_read_time
|
74
81
|
):
|
75
82
|
# Input checks
|
76
83
|
if not isinstance(nbits, (int, np.integer)):
|
@@ -78,6 +85,8 @@ class EMCCDDetectBase:
|
|
78
85
|
if nbits < 1 or nbits > 64:
|
79
86
|
raise EMCCDDetectException('nbits must be between 1 and 64, '
|
80
87
|
'inclusive')
|
88
|
+
if row_read_time < 0:
|
89
|
+
raise EMCCDDetectException('row_read_time must be >= 0 seconds.')
|
81
90
|
|
82
91
|
self.em_gain = em_gain
|
83
92
|
self.full_well_image = full_well_image
|
@@ -92,6 +101,7 @@ class EMCCDDetectBase:
|
|
92
101
|
self.eperdn = eperdn
|
93
102
|
self.nbits = nbits
|
94
103
|
self.numel_gain_register = numel_gain_register
|
104
|
+
self.row_read_time = row_read_time
|
95
105
|
|
96
106
|
# Placeholders for trap parameters
|
97
107
|
self.parallel_ccd = None
|
@@ -246,6 +256,43 @@ class EMCCDDetectBase:
|
|
246
256
|
return output_dn.reshape(actualized_e.shape)
|
247
257
|
|
248
258
|
def integrate(self, fluxmap_full, frametime, exposed_pix_m):
|
259
|
+
# apply non-uniformity of pixel responsivity via master flat
|
260
|
+
if hasattr(self, 'flat_path'):
|
261
|
+
if self.flat_path is not None:
|
262
|
+
with fits.open(self.flat_path) as hdul:
|
263
|
+
self.flat = hdul[1].data
|
264
|
+
if (self.flat < 0).any():
|
265
|
+
raise EMCCDDetectException('Master flat must not contain '
|
266
|
+
'negative values.')
|
267
|
+
if self.flat.shape != fluxmap_full.shape:
|
268
|
+
imaging_area_ones = np.ones_like(fluxmap_full)
|
269
|
+
# Attempt to embed the flat within the
|
270
|
+
# imaging+shielded area
|
271
|
+
self.flat_im = self.meta.embed_im(imaging_area_ones,
|
272
|
+
'image', self.flat.copy())
|
273
|
+
if self.flat_im.shape != fluxmap_full.shape:
|
274
|
+
raise EMCCDDetectException('Master flat shape must '
|
275
|
+
'agree with shape of fluxmap.')
|
276
|
+
else:
|
277
|
+
fluxmap_full *= self.flat_im
|
278
|
+
else:
|
279
|
+
fluxmap_full *= self.flat
|
280
|
+
|
281
|
+
# simulate smear to fluxmap
|
282
|
+
# credit for this smearing code: Peter Williams, Tellus1, 2024
|
283
|
+
# XXX Technically, smearing adds electrons to each pixel, which
|
284
|
+
# increases the chance of charge capture for CTI, but simulating
|
285
|
+
# this small effect would require hacking arCTIc.
|
286
|
+
smear = np.zeros_like(fluxmap_full)
|
287
|
+
m = len(smear)
|
288
|
+
for r in range(m):
|
289
|
+
columnsum = 0
|
290
|
+
for i in range(r+1):
|
291
|
+
columnsum = columnsum + self.row_read_time*fluxmap_full[i,:]
|
292
|
+
smear[r,:] = columnsum
|
293
|
+
|
294
|
+
fluxmap_full = fluxmap_full + smear/frametime
|
295
|
+
|
249
296
|
# Add cosmic ray effects
|
250
297
|
# XXX Maybe change this to units of flux later
|
251
298
|
cosm_actualized_e = cosmic_hits(np.zeros_like(fluxmap_full),
|
@@ -503,7 +550,7 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
503
550
|
full_well_image : float
|
504
551
|
Image area full well capacity (e-). Defaults to 78000.
|
505
552
|
full_well_serial : float
|
506
|
-
Serial (gain) register full well capacity (e-). Defaults to
|
553
|
+
Serial (gain) register full well capacity (e-). Defaults to 105000.
|
507
554
|
dark_current: float
|
508
555
|
Dark current rate (e-/pix/s). Defaults to 0.00031.
|
509
556
|
cic : float
|
@@ -519,7 +566,7 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
519
566
|
pixel_pitch : float
|
520
567
|
Distance between pixel centers (m). Defaults to 13e-6.
|
521
568
|
eperdn : float
|
522
|
-
Electrons per dn. Defaults to
|
569
|
+
Electrons per dn. Defaults to 8.2.
|
523
570
|
nbits : int
|
524
571
|
Number of bits used by the ADC readout. Must be between 1 and 64,
|
525
572
|
inclusive. Defaults to 14.
|
@@ -532,15 +579,28 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
532
579
|
nonlin_path : str
|
533
580
|
Path of nonlinearity correction file. See doc string of
|
534
581
|
nonlinearity.apply_relgains for details on the required
|
535
|
-
format of the file. If None,
|
536
|
-
nonlinearity.
|
582
|
+
format of the file. If None, no application of
|
583
|
+
nonlinearity is performed. Defaults to None.
|
584
|
+
row_read_time : float
|
585
|
+
Time in seconds for each row to move into the first register (same as
|
586
|
+
the time for each row to be clocked toward the register). This is used
|
587
|
+
to simulate smear on the image due to clocking during the exposure to
|
588
|
+
light. Especially useful for shutterless EMCCDs. If 0, no smear is
|
589
|
+
simulated. Defaults to 0 seconds.
|
590
|
+
flat_path : str
|
591
|
+
Path of master flat file. Assumed to be a FITS file for which the flat
|
592
|
+
data resides in the first extension HDU. The flat is assumed to be
|
593
|
+
of image-area shape (specified by the metadata from meta_path),
|
594
|
+
dark-subtracted, divided by k-gain, divided by EM gain, and desmeared.
|
595
|
+
If the input is None, no application of pixel nonuniformity is
|
596
|
+
performed. Defaults to None.
|
537
597
|
|
538
598
|
"""
|
539
599
|
def __init__(
|
540
600
|
self,
|
541
601
|
em_gain=1.,
|
542
602
|
full_well_image=78000.,
|
543
|
-
full_well_serial=
|
603
|
+
full_well_serial=105000.,
|
544
604
|
dark_current=0.00031,
|
545
605
|
cic=0.016,
|
546
606
|
read_noise=110.,
|
@@ -548,11 +608,13 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
548
608
|
qe=0.9,
|
549
609
|
cr_rate=0.,
|
550
610
|
pixel_pitch=13e-6,
|
551
|
-
eperdn=
|
611
|
+
eperdn=8.2,
|
552
612
|
nbits=14,
|
553
613
|
numel_gain_register=604,
|
554
614
|
meta_path=None,
|
555
|
-
nonlin_path=None
|
615
|
+
nonlin_path=None,
|
616
|
+
row_read_time=0, # seconds
|
617
|
+
flat_path=None
|
556
618
|
):
|
557
619
|
# If no metadata file path specified, default to metadata.yaml in util
|
558
620
|
if meta_path is None:
|
@@ -563,13 +625,8 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
563
625
|
self.meta_path = meta_path
|
564
626
|
self.meta = MetadataWrapper(self.meta_path)
|
565
627
|
|
566
|
-
# Set defaults from metadata
|
567
|
-
if full_well_serial is None:
|
568
|
-
full_well_serial = self.meta.fwc
|
569
|
-
if eperdn is None:
|
570
|
-
eperdn = self.meta.eperdn
|
571
|
-
|
572
628
|
self.nonlin_path = nonlin_path
|
629
|
+
self.flat_path = flat_path
|
573
630
|
|
574
631
|
super().__init__(
|
575
632
|
em_gain=em_gain,
|
@@ -584,7 +641,8 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
584
641
|
pixel_pitch=pixel_pitch,
|
585
642
|
eperdn=eperdn,
|
586
643
|
nbits=nbits,
|
587
|
-
numel_gain_register=numel_gain_register
|
644
|
+
numel_gain_register=numel_gain_register,
|
645
|
+
row_read_time=row_read_time
|
588
646
|
)
|
589
647
|
|
590
648
|
def sim_full_frame(self, fluxmap, frametime):
|
@@ -687,6 +745,12 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
687
745
|
Bias subtracted, gain divided frame in units of e-.
|
688
746
|
|
689
747
|
"""
|
748
|
+
if hasattr(self, 'nonlin_path'):
|
749
|
+
if self.nonlin_path is not None:
|
750
|
+
nonlin_factors = apply_relgains(frame_dn, self.em_gain,
|
751
|
+
self.nonlin_path)
|
752
|
+
# correct fo nonlin by dividing
|
753
|
+
frame_dn = frame_dn/nonlin_factors
|
690
754
|
return (frame_dn * self.eperdn - self.bias) / self.em_gain
|
691
755
|
|
692
756
|
|
@@ -778,7 +842,8 @@ def emccd_detect(
|
|
778
842
|
pixel_pitch=pixel_pitch,
|
779
843
|
eperdn=1.,
|
780
844
|
nbits=64,
|
781
|
-
numel_gain_register=604
|
845
|
+
numel_gain_register=604,
|
846
|
+
row_read_time=0
|
782
847
|
)
|
783
848
|
|
784
849
|
return emccd.sim_sub_frame(fluxmap, frametime).astype(float)
|
emccd_detect/util/metadata.yaml
CHANGED
@@ -22,20 +22,6 @@ class Metadata(object):
|
|
22
22
|
Data from metadata file.
|
23
23
|
geom : SimpleNamespace
|
24
24
|
Geometry specific data.
|
25
|
-
eperdn : float
|
26
|
-
Electrons per dn conversion factor (detector k gain).
|
27
|
-
fwc : float
|
28
|
-
Full well capacity of detector.
|
29
|
-
sat_thresh : float
|
30
|
-
Multiplication factor for fwc that determines saturated cosmic pixels.
|
31
|
-
plat_thresh : float
|
32
|
-
Multiplication factor for fwc that determines edges of cosmic plateu.
|
33
|
-
cosm_filter : int
|
34
|
-
Minimum length in pixels of cosmic plateus to be identified.
|
35
|
-
tail_filter : int
|
36
|
-
Moving median filter window size for cosmic tail subtraction.
|
37
|
-
cic_thresh : float
|
38
|
-
Multiplication factor for readnoise that determines beginning of cic.
|
39
25
|
|
40
26
|
B Nemati and S Miller - UAH - 03-Aug-2018
|
41
27
|
|
@@ -48,13 +34,6 @@ class Metadata(object):
|
|
48
34
|
self.frame_rows = self.data['frame_rows']
|
49
35
|
self.frame_cols = self.data['frame_cols']
|
50
36
|
self.geom = self.data['geom']
|
51
|
-
self.eperdn = self.data['eperdn']
|
52
|
-
self.fwc = self.data['fwc']
|
53
|
-
self.sat_thresh = self.data['sat_thresh']
|
54
|
-
self.plat_thresh = self.data['plat_thresh']
|
55
|
-
self.cosm_filter = self.data['cosm_filter']
|
56
|
-
self.tail_filter = self.data['tail_filter']
|
57
|
-
self.cic_thresh = self.data['cic_thresh']
|
58
37
|
|
59
38
|
def get_data(self):
|
60
39
|
"""Read yaml data into dictionary."""
|
@@ -23,20 +23,6 @@ class MetadataWrapper(Metadata):
|
|
23
23
|
Data from metadata file.
|
24
24
|
geom : SimpleNamespace
|
25
25
|
Geometry specific data.
|
26
|
-
eperdn : float
|
27
|
-
Electrons per dn conversion factor (detector k gain).
|
28
|
-
fwc : float
|
29
|
-
Full well capacity of detector.
|
30
|
-
sat_thresh : float
|
31
|
-
Multiplication factor for fwc that determines saturated cosmic pixels.
|
32
|
-
plat_thresh : float
|
33
|
-
Multiplication factor for fwc that determines edges of cosmic plateu.
|
34
|
-
cosm_filter : int
|
35
|
-
Minimum length in pixels of cosmic plateus to be identified.
|
36
|
-
tail_filter : int
|
37
|
-
Moving median filter window size for cosmic tail subtraction.
|
38
|
-
cic_thresh : float
|
39
|
-
Multiplication factor for readnoise that determines beginning of cic.
|
40
26
|
|
41
27
|
"""
|
42
28
|
|
@@ -1,23 +1,21 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: emccd_detect
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.5.0
|
4
4
|
Summary: EMCCD detector image simulation
|
5
|
-
Author: Bijan Nemati
|
6
|
-
Author-email: bijan.nemati@tellus1.com, sam.miller@uah.edu, kevin.ludwick@uah.edu
|
5
|
+
Author-email: Bijan Nemati <bijan.nemati@tellus1.com>, Sam Miller <sam.miller@uah.edu>, Kevin Ludwick <kevin.ludwick@uah.edu>
|
7
6
|
Classifier: Development Status :: 4 - Beta
|
8
7
|
Classifier: Intended Audience :: Developers
|
9
8
|
Classifier: Programming Language :: Python :: 3
|
10
|
-
Classifier: Programming Language :: Python :: 3.6
|
11
|
-
Classifier: Programming Language :: Python :: 3.7
|
12
|
-
Classifier: Programming Language :: Python :: 3.8
|
13
9
|
Requires-Python: >=3.6
|
14
10
|
Description-Content-Type: text/markdown
|
11
|
+
License-File: LICENSE.txt
|
15
12
|
Requires-Dist: astropy
|
16
13
|
Requires-Dist: matplotlib
|
17
14
|
Requires-Dist: numpy
|
18
15
|
Requires-Dist: scipy
|
19
|
-
Requires-Dist: pynufft
|
16
|
+
Requires-Dist: pynufft==2020.0.0
|
20
17
|
Requires-Dist: pyyaml
|
18
|
+
Dynamic: license-file
|
21
19
|
|
22
20
|
# EMCCD Detect
|
23
21
|
|
@@ -26,7 +24,9 @@ Given an input fluxmap, emccd_detect will return a simulated EMCCD detector imag
|
|
26
24
|
|
27
25
|
# Version
|
28
26
|
|
29
|
-
The latest version of emccd\_detect is 2.
|
27
|
+
The latest version of emccd\_detect is 2.5.0. Main differences from previous version, 2.4.0:
|
28
|
+
--the ability to implement smear due to exposure of some rows while others are being read out. Credit for this smearing code: Peter Williams, Tellus1, 2024.
|
29
|
+
--the ability to implement non-uniformity in pixel response via an input master flat. Assumed to be a FITS file.
|
30
30
|
|
31
31
|
|
32
32
|
## Getting Started
|
@@ -0,0 +1,14 @@
|
|
1
|
+
emccd_detect/__init__.py,sha256=uWZwY5HGOMhZbYvLBHUIJ1__9KWeLAx2rdkOL0oplTg,45
|
2
|
+
emccd_detect/cosmics.py,sha256=wRE47QOB3fwxkH5PHTeoyLjJ0fgJki6Z8hLDPx2h3SQ,3991
|
3
|
+
emccd_detect/emccd_detect.py,sha256=tjNLAZP4N2WlU3jluD1tww4CmM3T1gxw46aL3cw_CR0,30223
|
4
|
+
emccd_detect/nonlinearity.py,sha256=DWBGjoShInMXBX0BLj6lT9dlY_lx6pdn8VU84jk_djU,4938
|
5
|
+
emccd_detect/rand_em_gain.py,sha256=3eF9T7PNYFZT0coGZwBmNTYz6B9pj2lXxTR8ROG6_7Q,6297
|
6
|
+
emccd_detect/util/__init__.py,sha256=iwhKnzeBJLKxpRVjvzwiRE63_zNpIBfaKLITauVph-0,24
|
7
|
+
emccd_detect/util/metadata.yaml,sha256=G0-Uy3wA7tmPXcoFS3ZD1iomIw4hvSRl58RGJjIJeLM,1034
|
8
|
+
emccd_detect/util/read_metadata.py,sha256=YgqdGJrWCqO0VUJ9gTrUYxK0wjI8NyqEwyodIgllDAE,1805
|
9
|
+
emccd_detect/util/read_metadata_wrapper.py,sha256=Em22IK3s9ZL-4H-g7yvJVlhdYd4Vez_MLflPdnJldJg,4848
|
10
|
+
emccd_detect-2.5.0.dist-info/licenses/LICENSE.txt,sha256=k8FrCPoTUgsCsv9PNH_OLV9tcPdnAlUeU_YQOSJLcfc,1100
|
11
|
+
emccd_detect-2.5.0.dist-info/METADATA,sha256=mbhbsf05RUYmLvOLpkZaZ8Q9Sn3K5k7PZeG7rAUCzfo,3082
|
12
|
+
emccd_detect-2.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
13
|
+
emccd_detect-2.5.0.dist-info/top_level.txt,sha256=V0qxOcGf8TowSJXnTxWEMuK9BBsySwhtKNitfdokD0A,13
|
14
|
+
emccd_detect-2.5.0.dist-info/RECORD,,
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Bijan Nemati, Sam Miller, and Kevin Ludwick
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -1,13 +0,0 @@
|
|
1
|
-
emccd_detect/__init__.py,sha256=FwzLqOGO--eOgOxuK6wCfzsc5yCUneMzLELAeD7Rc7Q,45
|
2
|
-
emccd_detect/cosmics.py,sha256=wRE47QOB3fwxkH5PHTeoyLjJ0fgJki6Z8hLDPx2h3SQ,3991
|
3
|
-
emccd_detect/emccd_detect.py,sha256=iOLp-I6NibxJeZwmb7V5cqo5xZI3BxV5XB-1AcQLnac,26678
|
4
|
-
emccd_detect/nonlinearity.py,sha256=DWBGjoShInMXBX0BLj6lT9dlY_lx6pdn8VU84jk_djU,4938
|
5
|
-
emccd_detect/rand_em_gain.py,sha256=3eF9T7PNYFZT0coGZwBmNTYz6B9pj2lXxTR8ROG6_7Q,6297
|
6
|
-
emccd_detect/util/__init__.py,sha256=iwhKnzeBJLKxpRVjvzwiRE63_zNpIBfaKLITauVph-0,24
|
7
|
-
emccd_detect/util/metadata.yaml,sha256=hcKTg4kMy12dfbCmmvZeKEqjeUA3BYiAcZc5vZpc3bE,1149
|
8
|
-
emccd_detect/util/read_metadata.py,sha256=r511ENJ6zbIvLDWiVic7KsVXYrBphSdTKUQbuwocjLs,2764
|
9
|
-
emccd_detect/util/read_metadata_wrapper.py,sha256=oBh2KpJ-uLTSIY_hPzw8sNIcJ6MENBSf38ks8OaFOSQ,5473
|
10
|
-
emccd_detect-2.4.0.dist-info/METADATA,sha256=sX4JDwVH__aNVtFOAliynk1oLCiMwLSokSACT6noa9g,3039
|
11
|
-
emccd_detect-2.4.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
12
|
-
emccd_detect-2.4.0.dist-info/top_level.txt,sha256=V0qxOcGf8TowSJXnTxWEMuK9BBsySwhtKNitfdokD0A,13
|
13
|
-
emccd_detect-2.4.0.dist-info/RECORD,,
|
File without changes
|