emccd-detect 2.6.0__tar.gz → 2.6.2__tar.gz
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-2.6.0 → emccd_detect-2.6.2}/PKG-INFO +9 -9
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/README.md +8 -8
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect/__init__.py +1 -1
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect/emccd_detect.py +68 -25
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect/rand_em_gain.py +27 -18
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect/util/fpn_map.fits +0 -0
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect.egg-info/PKG-INFO +9 -9
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect.egg-info/top_level.txt +1 -1
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/pyproject.toml +1 -1
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/LICENSE.txt +0 -0
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect/cosmics.py +0 -0
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect/nonlinearity.py +0 -0
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect/partial_CIC_MLE.py +0 -0
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect/util/__init__.py +0 -0
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect/util/metadata.yaml +0 -0
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect/util/read_metadata.py +0 -0
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect/util/read_metadata_wrapper.py +0 -0
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect.egg-info/SOURCES.txt +0 -0
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect.egg-info/dependency_links.txt +0 -0
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/emccd_detect.egg-info/requires.txt +0 -0
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/setup.cfg +0 -0
- {emccd_detect-2.6.0 → emccd_detect-2.6.2}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: emccd_detect
|
|
3
|
-
Version: 2.6.
|
|
3
|
+
Version: 2.6.2
|
|
4
4
|
Summary: EMCCD detector image simulation
|
|
5
5
|
Author: Joshua Ludwick
|
|
6
6
|
Author-email: Bijan Nemati <bijan.nemati@tellus1.com>, Sam Miller <sam.miller@uah.edu>, Kevin Ludwick <kevin.ludwick@uah.edu>
|
|
@@ -25,14 +25,14 @@ Given an input fluxmap, emccd_detect will return a simulated EMCCD detector imag
|
|
|
25
25
|
|
|
26
26
|
# Version
|
|
27
27
|
|
|
28
|
-
The latest version of emccd\_detect is 2.6.
|
|
29
|
-
Main differences from previous version:
|
|
30
|
-
--cosmic rays are more accurate, more like what the Roman CGI expects to see at L2 (including secondary cosmic ray events due to the shielding surrounding CGI). Almost nothing is hard coded about the cosmic rays. The tail length can be tuned as well.
|
|
31
|
-
--Fixed-pattern noise (FPN) is now implemented: 'roman' for Roman FPN found in TVAC, custom input file, or stripe pattern in rows and/or columns. File for Roman FPN included in util folder.
|
|
32
|
-
--CIC in gain register ("partial CIC") implemented (defaults to no partial CIC). One can specify particular "hot" gain stages with respect to CIC as well.
|
|
33
|
-
--EM gain simulation now conforms to exact binomial branching process instead of the approximate Gamma distribution. fast_gain_mode allows (fine for gain >~ 200) is available and uses the Gamma distribution.
|
|
34
|
-
--"Hot" gain stages with respect to EM gain multiplication also implemented. Defaults to None.
|
|
35
|
-
--Hot pixel map input available.
|
|
28
|
+
The latest version of emccd\_detect is 2.6.2. Main differences from previous version, 2.5.0:
|
|
29
|
+
Main differences from previous version:
|
|
30
|
+
--cosmic rays are more accurate, more like what the Roman CGI expects to see at L2 (including secondary cosmic ray events due to the shielding surrounding CGI). Almost nothing is hard coded about the cosmic rays. The tail length can be tuned as well.
|
|
31
|
+
--Fixed-pattern noise (FPN) is now implemented: 'roman' for Roman FPN found in TVAC, custom input file, or stripe pattern in rows and/or columns. File for Roman FPN included in util folder.
|
|
32
|
+
--CIC in gain register ("partial CIC") implemented (defaults to no partial CIC). One can specify particular "hot" gain stages with respect to CIC as well.
|
|
33
|
+
--EM gain simulation now conforms to exact binomial branching process instead of the approximate Gamma distribution. fast_gain_mode allows (fine for gain >~ 200) is available and uses the Gamma distribution.
|
|
34
|
+
--"Hot" gain stages with respect to EM gain multiplication also implemented. Defaults to None.
|
|
35
|
+
--Hot pixel map input available.
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
## Getting Started
|
|
@@ -5,14 +5,14 @@ Given an input fluxmap, emccd_detect will return a simulated EMCCD detector imag
|
|
|
5
5
|
|
|
6
6
|
# Version
|
|
7
7
|
|
|
8
|
-
The latest version of emccd\_detect is 2.6.
|
|
9
|
-
Main differences from previous version:
|
|
10
|
-
--cosmic rays are more accurate, more like what the Roman CGI expects to see at L2 (including secondary cosmic ray events due to the shielding surrounding CGI). Almost nothing is hard coded about the cosmic rays. The tail length can be tuned as well.
|
|
11
|
-
--Fixed-pattern noise (FPN) is now implemented: 'roman' for Roman FPN found in TVAC, custom input file, or stripe pattern in rows and/or columns. File for Roman FPN included in util folder.
|
|
12
|
-
--CIC in gain register ("partial CIC") implemented (defaults to no partial CIC). One can specify particular "hot" gain stages with respect to CIC as well.
|
|
13
|
-
--EM gain simulation now conforms to exact binomial branching process instead of the approximate Gamma distribution. fast_gain_mode allows (fine for gain >~ 200) is available and uses the Gamma distribution.
|
|
14
|
-
--"Hot" gain stages with respect to EM gain multiplication also implemented. Defaults to None.
|
|
15
|
-
--Hot pixel map input available.
|
|
8
|
+
The latest version of emccd\_detect is 2.6.2. Main differences from previous version, 2.5.0:
|
|
9
|
+
Main differences from previous version:
|
|
10
|
+
--cosmic rays are more accurate, more like what the Roman CGI expects to see at L2 (including secondary cosmic ray events due to the shielding surrounding CGI). Almost nothing is hard coded about the cosmic rays. The tail length can be tuned as well.
|
|
11
|
+
--Fixed-pattern noise (FPN) is now implemented: 'roman' for Roman FPN found in TVAC, custom input file, or stripe pattern in rows and/or columns. File for Roman FPN included in util folder.
|
|
12
|
+
--CIC in gain register ("partial CIC") implemented (defaults to no partial CIC). One can specify particular "hot" gain stages with respect to CIC as well.
|
|
13
|
+
--EM gain simulation now conforms to exact binomial branching process instead of the approximate Gamma distribution. fast_gain_mode allows (fine for gain >~ 200) is available and uses the Gamma distribution.
|
|
14
|
+
--"Hot" gain stages with respect to EM gain multiplication also implemented. Defaults to None.
|
|
15
|
+
--Hot pixel map input available.
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
## Getting Started
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
__version__ = '2.6.
|
|
2
|
+
__version__ = '2.6.2'
|
|
@@ -36,6 +36,14 @@ except:
|
|
|
36
36
|
# Partial CIC is observationally degenerate with the effect of surface traps which release a captured trap
|
|
37
37
|
# many pixels downstream. Probability of capture increases with charge packeet (probability ~1 for ~100e- or higher).
|
|
38
38
|
# Small effect for low to moderate EM gains.
|
|
39
|
+
|
|
40
|
+
# NOTE A value of Q=1e-3 was found using maximum likelihood estimation from real
|
|
41
|
+
# Roman testbed data at a commanded gain of 5000, which serves as a benchmark value. However,
|
|
42
|
+
# the model used for the fit used an approximate form for the partial CIC probability, out of computational necessity,
|
|
43
|
+
# which used an average gain stage value which was representative of all the stages,
|
|
44
|
+
# so the fitted value of 1e-3 is physically akin to the middle stages having that value. It was verified
|
|
45
|
+
# that this is similar to P/40 for all the stages.
|
|
46
|
+
|
|
39
47
|
class EMCCDDetectException(Exception):
|
|
40
48
|
"""Exception class for emccd_detect module."""
|
|
41
49
|
|
|
@@ -87,7 +95,8 @@ class EMCCDDetectBase:
|
|
|
87
95
|
pixel_pitch,
|
|
88
96
|
eperdn,
|
|
89
97
|
nbits,
|
|
90
|
-
numel_gain_register
|
|
98
|
+
numel_gain_register,
|
|
99
|
+
**kwargs
|
|
91
100
|
):
|
|
92
101
|
# Input checks
|
|
93
102
|
if not isinstance(nbits, (int, np.integer)):
|
|
@@ -566,7 +575,7 @@ class EMCCDDetectBase:
|
|
|
566
575
|
# is effectively performed with sat_tails() afterwards.
|
|
567
576
|
gain_counts = np.zeros_like(serial_counts)
|
|
568
577
|
if not hasattr(self, 'fast_gain_mode'):
|
|
569
|
-
self.fast_gain_mode = False # use
|
|
578
|
+
self.fast_gain_mode = False # use accurate method in this case
|
|
570
579
|
if not hasattr(self, 'gain_stage_specs'):
|
|
571
580
|
self.gain_stage_specs = None # default value
|
|
572
581
|
all_gain_stage_specs = {n: self.em_gain**(1/self.numel_gain_register) - 1 for n in range(1, self.numel_gain_register+1)}
|
|
@@ -574,10 +583,15 @@ class EMCCDDetectBase:
|
|
|
574
583
|
for num_stages_left in range(1, self.numel_gain_register+1):
|
|
575
584
|
if num_stages_left in self.gain_stage_specs.keys():
|
|
576
585
|
all_gain_stage_specs[num_stages_left] = self.gain_stage_specs[num_stages_left]
|
|
586
|
+
if hasattr(self, 'n1_fast'):
|
|
587
|
+
n1_fast = False #handle n=1 case using slow, accurate method regardless of gain value
|
|
588
|
+
else:
|
|
589
|
+
n1_fast = self.fast_gain_mode # inherent this bool in this case
|
|
577
590
|
gain_counts = rand_em_gain(
|
|
578
591
|
n_in_array=serial_counts,
|
|
579
592
|
gain_stage_specs=all_gain_stage_specs,
|
|
580
|
-
numel_gain_register=self.numel_gain_register, fast_gain_mode=self.fast_gain_mode
|
|
593
|
+
numel_gain_register=self.numel_gain_register, fast_gain_mode=self.fast_gain_mode,
|
|
594
|
+
n1_fast=n1_fast
|
|
581
595
|
)
|
|
582
596
|
|
|
583
597
|
# assuming partial CIC independently propagates through gain register
|
|
@@ -597,7 +611,7 @@ class EMCCDDetectBase:
|
|
|
597
611
|
# no EM gain(?), so we simulate these effects here.
|
|
598
612
|
# The traps in the gain register are simulated in sat_tails here.
|
|
599
613
|
if not hasattr(self, 'tail_length'):
|
|
600
|
-
self.tail_length = 40 # default value
|
|
614
|
+
self.tail_length = int(np.round(self.em_gain*40/1000)) # default value
|
|
601
615
|
gain_counts_tails = sat_tails(gain_counts, self.full_well_serial, self.tail_length)
|
|
602
616
|
|
|
603
617
|
return gain_counts_tails
|
|
@@ -636,13 +650,13 @@ class EMCCDDetectBase:
|
|
|
636
650
|
self.fpn = hdul[0].data
|
|
637
651
|
elif self.fpn_path == "roman":
|
|
638
652
|
if serial_counts.shape[0] == self.meta.data['frame_rows'] and serial_counts.shape[1] == self.meta.data['frame_cols']:
|
|
639
|
-
with fits.open(Path(here, 'util', '
|
|
653
|
+
with fits.open(Path(here, 'util', 'fpn_map.fits')) as hdul:
|
|
640
654
|
frame_data = hdul[0].data
|
|
641
655
|
self.fpn = frame_data
|
|
642
656
|
elif serial_counts.shape[0] <= self.meta.data['geom']['image']['rows'] and serial_counts.shape[1] <= self.meta.data['geom']['image']['cols']:
|
|
643
657
|
#If the area specificed by the user is not full frame then
|
|
644
658
|
#this code cuts out a portion/the entire image area on the fpn map to apply to amp
|
|
645
|
-
with fits.open(Path(here, 'util', '
|
|
659
|
+
with fits.open(Path(here, 'util', 'fpn_map.fits')) as hdul:
|
|
646
660
|
frame_data = hdul[0].data
|
|
647
661
|
r0c0 = self.meta.data['geom']['image']['r0c0']
|
|
648
662
|
subframe_array = frame_data[r0c0[0]:r0c0[0]+serial_counts.shape[0], r0c0[1]:r0c0[1]+serial_counts.shape[1]]
|
|
@@ -746,9 +760,11 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
|
746
760
|
oversample_factor : int
|
|
747
761
|
Factor of oversampling of cosmic Gaussian over which to bin-sum to get
|
|
748
762
|
pixel values. Default is 10.
|
|
749
|
-
tail_length: int
|
|
750
|
-
|
|
751
|
-
|
|
763
|
+
tail_length: int or str
|
|
764
|
+
Desired tail length of cosmic ray (in pixels). Defaults to 'roman', which gives a
|
|
765
|
+
tail length of about 40 for EM gain of 1000 (what is expected in flight
|
|
766
|
+
for the Roman Telescope) and shorter lengths for proportionally smaller EM gain.
|
|
767
|
+
For example, a gain of 500 would mean a tail length of 20 in the 'roman' case.
|
|
752
768
|
pixel_pitch : float
|
|
753
769
|
Distance between pixel centers (m). Defaults to 13e-6.
|
|
754
770
|
eperdn : float
|
|
@@ -795,14 +811,15 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
|
795
811
|
the time for each row to be clocked toward the register). This is used
|
|
796
812
|
to simulate smear on the image due to clocking during the exposure to
|
|
797
813
|
light. Especially useful for shutterless EMCCDs. If 0, no smear is
|
|
798
|
-
simulated. Defaults to
|
|
799
|
-
gain_CIC_Q : float
|
|
814
|
+
simulated. Defaults to 223.5e-6 seconds (applicable to the Roman CGI).
|
|
815
|
+
gain_CIC_Q : float or str
|
|
800
816
|
Probability Q (or mean rate) of production of a clock-induced charge (CIC)
|
|
801
817
|
in a given gain register stage. We call this "partial CIC".
|
|
802
818
|
Physically, Q < P, where P is the average probability of charge multiplication
|
|
803
819
|
for a single gain stage, and em_gain = (1+P)^numel_gain_register.
|
|
804
820
|
To simulate no partial CIC, let this input be 0.
|
|
805
|
-
Defaults to
|
|
821
|
+
Defaults to 'roman', in which case P/40 is used, which is consistent with data
|
|
822
|
+
and gives negligible partial CIC for lower gains as expected.
|
|
806
823
|
gain_CIC_specs: dict or None
|
|
807
824
|
This input supercedes gain_CIC_Q and renders the value of gain_CIC_Q
|
|
808
825
|
irrelevant. This is used for specifying particular "hot" stages which source the
|
|
@@ -827,11 +844,15 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
|
827
844
|
If a float, it must be between 0 and 1. If < 0.5, overspill to the row downstream is
|
|
828
845
|
more likely than upstream overspill. Defaults to 0.7. Upstream overspill
|
|
829
846
|
is more likely for the Roman CGI EMCCDs.
|
|
830
|
-
fast_gain_mode : bool
|
|
847
|
+
fast_gain_mode : bool or 'auto'
|
|
831
848
|
If True, a faster but less accurate method (uses Erlang/Gamma distribution for EM gain)
|
|
832
849
|
of simulating the gain register is used. If False, a slower but more accurate method
|
|
833
850
|
(marches each pixel through the gain register with binomial distribution) is used.
|
|
834
|
-
The fast method is quite accurate for em_gain > 200
|
|
851
|
+
The fast method is quite accurate for em_gain > 200 if the number of incoming particles
|
|
852
|
+
to the gain register is n > 1. If 'auto', both speed and accuracy
|
|
853
|
+
are prioritized: the fast method is used if em_gain > 200 (and n>1) and 'roman' is used for gain_CIC_Q,
|
|
854
|
+
and the slow method is used with gain_CIC_Q = 0 (since partial CIC is negligible for low gains)
|
|
855
|
+
for em_gain <= 200 (or if n=1 for any gain). Defaults to 'auto'.
|
|
835
856
|
gain_stage_specs: dict or None
|
|
836
857
|
This input is used for specifying particular gain stages which are "hot"
|
|
837
858
|
with respect to the average probability of multiplication, P. The input
|
|
@@ -882,7 +903,7 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
|
882
903
|
loc=1590,
|
|
883
904
|
scale=550,
|
|
884
905
|
oversample_factor=10,
|
|
885
|
-
tail_length=
|
|
906
|
+
tail_length='roman',
|
|
886
907
|
pixel_pitch=13e-6,
|
|
887
908
|
eperdn=8.2,
|
|
888
909
|
nbits=14,
|
|
@@ -891,19 +912,17 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
|
891
912
|
nonlin_path=None,
|
|
892
913
|
flat_path=None,
|
|
893
914
|
hot_pixel_path=None,
|
|
894
|
-
row_read_time=
|
|
895
|
-
gain_CIC_Q=
|
|
915
|
+
row_read_time=223.5e-6, # seconds
|
|
916
|
+
gain_CIC_Q='roman',
|
|
896
917
|
gain_CIC_specs=None,
|
|
897
918
|
upstream_spill_prob=0.7,
|
|
898
|
-
fast_gain_mode=
|
|
919
|
+
fast_gain_mode='auto',
|
|
899
920
|
gain_stage_specs=None,
|
|
900
921
|
fpn_path= 'roman',
|
|
901
922
|
bias_sigma_col=35,
|
|
902
|
-
bias_sigma_row=35
|
|
923
|
+
bias_sigma_row=35,
|
|
924
|
+
**kwargs #accommodating other keyword args for backward compatibility
|
|
903
925
|
):
|
|
904
|
-
|
|
905
|
-
if tail_length < 0:
|
|
906
|
-
raise EMCCDDetectException('tail_length cannot be negative.')
|
|
907
926
|
if row_read_time < 0:
|
|
908
927
|
raise EMCCDDetectException('row_read_time must be >= 0 seconds.')
|
|
909
928
|
if upstream_spill_prob is not None:
|
|
@@ -934,10 +953,35 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
|
934
953
|
if num_stages_left in gain_stage_specs.keys():
|
|
935
954
|
all_gain_stage_specs[num_stages_left] = gain_stage_specs[num_stages_left]
|
|
936
955
|
self.avg_gain_P = np.sum(list(all_gain_stage_specs.values()))/numel_gain_register
|
|
937
|
-
|
|
956
|
+
# reset what the value is based gain_CIC_specs
|
|
957
|
+
em_gain = (1+self.avg_gain_P)**numel_gain_register
|
|
958
|
+
if fast_gain_mode == 'auto':
|
|
959
|
+
self.n1_fast = False # if n=1, use accurate method no matter what the gain; only defined if 'auto' mode used
|
|
960
|
+
if em_gain <= 200:
|
|
961
|
+
fast_gain_mode = False
|
|
962
|
+
gain_CIC_Q = 0
|
|
963
|
+
gain_CIC_specs = None
|
|
964
|
+
else:
|
|
965
|
+
fast_gain_mode = True
|
|
966
|
+
gain_CIC_Q = 'roman'
|
|
967
|
+
gain_CIC_specs = None
|
|
968
|
+
if type(tail_length) != int and tail_length != 'roman':
|
|
969
|
+
raise EMCCDDetectException("tail_length should be an integer or \'roman\'.")
|
|
970
|
+
elif type(tail_length) == int:
|
|
971
|
+
if tail_length < 0:
|
|
972
|
+
raise EMCCDDetectException('tail_length cannot be negative.')
|
|
973
|
+
elif tail_length == 'roman':
|
|
974
|
+
gain_avg = (1+self.avg_gain_P)**numel_gain_register
|
|
975
|
+
tail_length = int(np.round(gain_avg*40/1000))
|
|
976
|
+
if gain_CIC_Q != 'roman':
|
|
938
977
|
if gain_CIC_Q > self.avg_gain_P:
|
|
939
978
|
raise EMCCDDetectException('gain_CIC_Q >= P, where em_gain = '
|
|
940
979
|
'(1+P)^numel_gain_register. gain_CIC_Q must be < P.')
|
|
980
|
+
self.gain_CIC_Q = gain_CIC_Q
|
|
981
|
+
elif gain_CIC_Q == 'roman':
|
|
982
|
+
self.gain_CIC_Q = self.avg_gain_P/40
|
|
983
|
+
else:
|
|
984
|
+
raise EMCCDDetectException('gain_CIC_Q must be float or \'roman\'.')
|
|
941
985
|
if gain_CIC_specs is not None:
|
|
942
986
|
if not isinstance(gain_CIC_specs, dict):
|
|
943
987
|
raise EMCCDDetectException('gain_CIC_specs must either be None or a dictionary.')
|
|
@@ -973,9 +1017,8 @@ class EMCCDDetect(EMCCDDetectBase):
|
|
|
973
1017
|
self.row_read_time = row_read_time
|
|
974
1018
|
self.flat_path = flat_path
|
|
975
1019
|
self.hot_pixel_path = hot_pixel_path
|
|
976
|
-
self.gain_CIC_Q = gain_CIC_Q
|
|
977
1020
|
self.gain_CIC_specs = gain_CIC_specs
|
|
978
|
-
self.tail_length = tail_length
|
|
1021
|
+
self.tail_length = tail_length
|
|
979
1022
|
self.zff = zff
|
|
980
1023
|
self.loc = loc
|
|
981
1024
|
self.scale = scale
|
|
@@ -18,7 +18,7 @@ class RandEMGainException(Exception):
|
|
|
18
18
|
"""Exception class for rand_em_gain module."""
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
def rand_em_gain(n_in_array, gain_stage_specs, numel_gain_register, fast_gain_mode=False):
|
|
21
|
+
def rand_em_gain(n_in_array, gain_stage_specs, numel_gain_register, fast_gain_mode=False, n1_fast=False):
|
|
22
22
|
"""Generate random numbers according to EM gain pdfs.
|
|
23
23
|
|
|
24
24
|
Parameters
|
|
@@ -37,6 +37,10 @@ def rand_em_gain(n_in_array, gain_stage_specs, numel_gain_register, fast_gain_mo
|
|
|
37
37
|
of simulating the gain register is used. If False, a slower but more accurate method
|
|
38
38
|
(marches each pixel through the gain register with binomial distribution) is used.
|
|
39
39
|
The fast method is quite accurate for EM gain > 200. Defaults to False.
|
|
40
|
+
n1_fast : bool, optional
|
|
41
|
+
If True, the fast method is used for the case of n=1 incoming particles to the gain register.
|
|
42
|
+
If False, the slow method is used for the case of n=1 incoming particles to the gain register.
|
|
43
|
+
Defaults to False.
|
|
40
44
|
|
|
41
45
|
Returns
|
|
42
46
|
-------
|
|
@@ -58,21 +62,27 @@ def rand_em_gain(n_in_array, gain_stage_specs, numel_gain_register, fast_gain_mo
|
|
|
58
62
|
elif em_gain == 1:
|
|
59
63
|
return n_in_array
|
|
60
64
|
else:
|
|
61
|
-
n_out_array = _apply_gain(n_in_array, gain_stage_specs, numel_gain_register, fast_gain_mode)
|
|
65
|
+
n_out_array = _apply_gain(n_in_array, gain_stage_specs, numel_gain_register, fast_gain_mode, n1_fast)
|
|
62
66
|
return n_out_array
|
|
63
67
|
|
|
64
|
-
def _apply_gain(n_in_array, gain_stage_specs, numel_gain_register, fast_gain_mode):
|
|
68
|
+
def _apply_gain(n_in_array, gain_stage_specs, numel_gain_register, fast_gain_mode, n1_fast):
|
|
65
69
|
"""Apply a specific EM gain to all nonzero n_in values."""
|
|
66
70
|
# physically, integer values of electrons for Matsuo (Galton-Watson branching process) distribution.
|
|
67
71
|
# Otherwise, we try to keep e- values as floats since EM gain,
|
|
68
72
|
# k gain, nonlinearity, master flat, etc are calibrated assuming fractions of electrons, and
|
|
69
73
|
# we can get fractions of electrons here for particular gain values. So we just round
|
|
70
74
|
# DN output to integer at the end.
|
|
71
|
-
|
|
75
|
+
n_out_array = np.zeros_like(n_in_array)
|
|
72
76
|
if fast_gain_mode:
|
|
73
77
|
avg_P = np.sum(list(gain_stage_specs.values()))/numel_gain_register
|
|
74
78
|
em_gain = (1+avg_P)**numel_gain_register
|
|
75
|
-
|
|
79
|
+
if n1_fast:
|
|
80
|
+
n_out_array = np.random.gamma(n_in_array, em_gain)
|
|
81
|
+
else:
|
|
82
|
+
the_rest_inds = np.where(n_in_array > 1)
|
|
83
|
+
n1_inds = np.where(n_in_array == 1)
|
|
84
|
+
n_out_array[n1_inds] = _rand_pdf(np.round(n_in_array[n1_inds]), gain_stage_specs, numel_gain_register)
|
|
85
|
+
n_out_array[the_rest_inds] = np.random.gamma(n_in_array[the_rest_inds], em_gain)
|
|
76
86
|
else:
|
|
77
87
|
n_out_array = _rand_pdf(np.round(n_in_array), gain_stage_specs, numel_gain_register)
|
|
78
88
|
|
|
@@ -90,11 +100,10 @@ def _rand_pdf(n_in, gain_stage_specs, numel_gain_register):
|
|
|
90
100
|
n_out = n_in.astype(int)
|
|
91
101
|
except:
|
|
92
102
|
n_out = int(np.round(n_in))
|
|
93
|
-
rng = np.random.default_rng()
|
|
94
103
|
# reverse list so that you're counting down from stage n to stage 1
|
|
95
104
|
# Stage numbers mean the number of stages remaining
|
|
96
105
|
for stage, Q in reversed(list(gain_stage_specs.items())):
|
|
97
|
-
n_out +=
|
|
106
|
+
n_out += np.random.binomial(n_out, Q)
|
|
98
107
|
|
|
99
108
|
# # trinomial (P1 and P2):
|
|
100
109
|
# t = rng.binomial(n_out, Q)
|
|
@@ -311,14 +320,14 @@ def partial_CIC(array_size, gain_stage_specs, numel_gain_register, gain_CIC_Q,
|
|
|
311
320
|
stage_numbers = np.append(stage_numbers, stage).astype(int)
|
|
312
321
|
|
|
313
322
|
for i in range(len(stage_numbers)):
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
323
|
+
#gain = (1+P)**stage_numbers[i]
|
|
324
|
+
# gain_stage_specs is already ordered by construction, which ensures gain branching process is sequential
|
|
325
|
+
# So we take the first stage_numbers[i] elements of it
|
|
326
|
+
input_gain_stage_specs = dict(islice(gain_stage_specs.items(), stage_numbers[i]))
|
|
327
|
+
inds = np.where(stage_chunks[i] > 0)
|
|
328
|
+
if inds[0].size > 0:
|
|
329
|
+
n_out = rand_em_gain(stage_chunks[i][inds], input_gain_stage_specs, stage_numbers[i])
|
|
330
|
+
partial_CIC[inds] = partial_CIC[inds] + n_out
|
|
322
331
|
|
|
323
332
|
return partial_CIC
|
|
324
333
|
|
|
@@ -343,10 +352,10 @@ if __name__ == '__main__':
|
|
|
343
352
|
plt.yscale('log')
|
|
344
353
|
plt.grid(True)
|
|
345
354
|
|
|
346
|
-
|
|
347
|
-
|
|
355
|
+
g=1000; n=2; M=600
|
|
356
|
+
g=200; n=1; M=600
|
|
348
357
|
#g=500; n=2; M=604
|
|
349
|
-
g=3; n=100; M=604
|
|
358
|
+
#g=3; n=100; M=604
|
|
350
359
|
#g=3; n=10; M=604
|
|
351
360
|
#g=150; n=10; M=604
|
|
352
361
|
nmax=int(g*n*4)
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: emccd_detect
|
|
3
|
-
Version: 2.6.
|
|
3
|
+
Version: 2.6.2
|
|
4
4
|
Summary: EMCCD detector image simulation
|
|
5
5
|
Author: Joshua Ludwick
|
|
6
6
|
Author-email: Bijan Nemati <bijan.nemati@tellus1.com>, Sam Miller <sam.miller@uah.edu>, Kevin Ludwick <kevin.ludwick@uah.edu>
|
|
@@ -25,14 +25,14 @@ Given an input fluxmap, emccd_detect will return a simulated EMCCD detector imag
|
|
|
25
25
|
|
|
26
26
|
# Version
|
|
27
27
|
|
|
28
|
-
The latest version of emccd\_detect is 2.6.
|
|
29
|
-
Main differences from previous version:
|
|
30
|
-
--cosmic rays are more accurate, more like what the Roman CGI expects to see at L2 (including secondary cosmic ray events due to the shielding surrounding CGI). Almost nothing is hard coded about the cosmic rays. The tail length can be tuned as well.
|
|
31
|
-
--Fixed-pattern noise (FPN) is now implemented: 'roman' for Roman FPN found in TVAC, custom input file, or stripe pattern in rows and/or columns. File for Roman FPN included in util folder.
|
|
32
|
-
--CIC in gain register ("partial CIC") implemented (defaults to no partial CIC). One can specify particular "hot" gain stages with respect to CIC as well.
|
|
33
|
-
--EM gain simulation now conforms to exact binomial branching process instead of the approximate Gamma distribution. fast_gain_mode allows (fine for gain >~ 200) is available and uses the Gamma distribution.
|
|
34
|
-
--"Hot" gain stages with respect to EM gain multiplication also implemented. Defaults to None.
|
|
35
|
-
--Hot pixel map input available.
|
|
28
|
+
The latest version of emccd\_detect is 2.6.2. Main differences from previous version, 2.5.0:
|
|
29
|
+
Main differences from previous version:
|
|
30
|
+
--cosmic rays are more accurate, more like what the Roman CGI expects to see at L2 (including secondary cosmic ray events due to the shielding surrounding CGI). Almost nothing is hard coded about the cosmic rays. The tail length can be tuned as well.
|
|
31
|
+
--Fixed-pattern noise (FPN) is now implemented: 'roman' for Roman FPN found in TVAC, custom input file, or stripe pattern in rows and/or columns. File for Roman FPN included in util folder.
|
|
32
|
+
--CIC in gain register ("partial CIC") implemented (defaults to no partial CIC). One can specify particular "hot" gain stages with respect to CIC as well.
|
|
33
|
+
--EM gain simulation now conforms to exact binomial branching process instead of the approximate Gamma distribution. fast_gain_mode allows (fine for gain >~ 200) is available and uses the Gamma distribution.
|
|
34
|
+
--"Hot" gain stages with respect to EM gain multiplication also implemented. Defaults to None.
|
|
35
|
+
--Hot pixel map input available.
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
## Getting Started
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|