emccd-detect 2.2.5__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.
@@ -0,0 +1,2 @@
1
+ # -*- coding: utf-8 -*-
2
+ __version__ = '2.2.5'
@@ -0,0 +1,124 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Generate cosmic hits."""
3
+
4
+ import numpy as np
5
+
6
+
7
+ def cosmic_hits(image_frame, cr_rate, frametime, pixel_pitch, max_val):
8
+ """Generate cosmic hits.
9
+
10
+ This function does not return the values of the cosmics; instead it returns
11
+ the electron map which occurs as a result of the photelectric effect when
12
+ the cosmics strike the detector. This allows the user to ignore the
13
+ physical properties of the cosmics and focus only on their effect on the
14
+ detector. This is especially helpful when setting max_val greater than the
15
+ full well capacity, as it allows the user to create saturated cosmics.
16
+
17
+ Parameters
18
+ ----------
19
+ image_frame : array_like
20
+ Image area frame (e-).
21
+ cr_rate : float
22
+ Cosmic ray rate (hits/cm^2/s).
23
+ frametime : float
24
+ Frame time (s).
25
+ pixel_pitch : float
26
+ Distance between pixel centers (m).
27
+ max_val : float
28
+ Maximum value of cosmic hit (e-).
29
+
30
+ Returns
31
+ -------
32
+ image_frame : array_like
33
+ Image area frame with cosmics added (e-).
34
+
35
+ """
36
+ if cr_rate > 0:
37
+ # Find number of hits/frame
38
+ nr, nc = image_frame.shape
39
+ framesize = (nr*pixel_pitch * nc*pixel_pitch) / 10**-4 # cm^2
40
+ hits_per_second = cr_rate * framesize
41
+ hits_per_frame = int(round(hits_per_second * frametime))
42
+
43
+ # Generate hit locations
44
+ # Describe each hit as a gaussian centered at (hit_row, hit_col) and having
45
+ # a radius of hit_rad chosen between cr_min_radius and cr_max_radius
46
+ cr_min_radius = 0
47
+ cr_max_radius = 2
48
+ hit_row = np.random.uniform(low=0, high=nr-1, size=hits_per_frame)
49
+ hit_col = np.random.uniform(low=0, high=nc-1, size=hits_per_frame)
50
+ hit_rad = np.random.uniform(low=cr_min_radius, high=cr_max_radius,
51
+ size=hits_per_frame)
52
+
53
+ # Create hits
54
+ for i in range(hits_per_frame):
55
+ # Get pixels where cosmic lands
56
+ min_row = max(np.floor(hit_row[i] - hit_rad[i]).astype(int), 0)
57
+ max_row = min(np.ceil(hit_row[i] + hit_rad[i]).astype(int), nr-1)
58
+ min_col = max(np.floor(hit_col[i] - hit_rad[i]).astype(int), 0)
59
+ max_col = min(np.ceil(hit_col[i] + hit_rad[i]).astype(int), nc-1)
60
+ cols, rows = np.meshgrid(np.arange(min_col, max_col+1),
61
+ np.arange(min_row, max_row+1))
62
+
63
+ # Create gaussian
64
+ sigma = 0.5
65
+ a = 1 / (np.sqrt(2*np.pi) * sigma)
66
+ b = 2 * sigma**2
67
+ cosm_section = a * np.exp(-((rows-hit_row[i])**2 + (cols-hit_col[i])**2) / b)
68
+
69
+ # Scale by maximum value
70
+ cosm_section = cosm_section / np.max(cosm_section) * max_val
71
+
72
+ # Add cosmic to frame
73
+ image_frame[min_row:max_row+1, min_col:max_col+1] += cosm_section
74
+
75
+ return image_frame
76
+
77
+
78
+ def sat_tails(serial_frame, full_well_serial):
79
+ """Simulate tails created by serial register saturation.
80
+
81
+ This is most prevalent in cosmic hits.
82
+
83
+ Parameters
84
+ ----------
85
+ serial_frame : array_like
86
+ Serial register frame (e-).
87
+ full_well_serial : float
88
+ Serial (gain) register full well capacity (e-).
89
+
90
+ """
91
+ overflow = 0.
92
+ overflow_i = 0.
93
+ for i, pix in enumerate(serial_frame):
94
+ serial_frame[i] += _set_tail_val(overflow, overflow_i, i)
95
+
96
+ if serial_frame[i] > full_well_serial:
97
+ overflow = serial_frame[i] - full_well_serial
98
+ overflow_i = i
99
+
100
+ return serial_frame
101
+
102
+
103
+ def _set_tail_val(overflow, overflow_i, i):
104
+ relative_i = i+1 - overflow_i
105
+ tail_val = overflow * 1 / relative_i
106
+ if tail_val < 1000:
107
+ tail_val = 0
108
+
109
+ return tail_val
110
+
111
+
112
+ if __name__ == '__main__':
113
+ import matplotlib.pyplot as plt
114
+
115
+ full_well_serial = 90000
116
+
117
+ row = np.ones(100)
118
+ row[2] = full_well_serial * 2
119
+
120
+ tail_row = sat_tails(row, full_well_serial)
121
+
122
+ plt.figure()
123
+ plt.plot(tail_row)
124
+ plt.show()