daplis 1.1.1__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.
daplis/__init__.py ADDED
File without changes
File without changes
@@ -0,0 +1,399 @@
1
+ """Module for computing timestamp differences.
2
+
3
+ Compares all timestamps from the same cycle for the given pair of pixels
4
+ against a given value (delta_window). Differences in that window are saved
5
+ and returned as a list.
6
+
7
+ This file can also be imported as a module and contains the following
8
+ functions:
9
+
10
+ TODO remove
11
+ * calculate_differences_2212 - calculate timestamp differences for
12
+ the given pair of pixels. Works only with firmware version '2212'.
13
+
14
+ * calculate_differences_2212_fast - calculate timestamp differences for
15
+ the given pair of pixels. Works only with firmware version '2212'.
16
+ Uses a faster algorithm than the function above.
17
+
18
+ """
19
+
20
+ from typing import List
21
+ from warnings import warn
22
+
23
+ import numpy as np
24
+ import pandas as pd
25
+ from numpy import ndarray
26
+
27
+ from daplis.functions import utils
28
+
29
+
30
+ # TODO remove - deprecated
31
+ def calculate_differences_2212(
32
+ data: List[float],
33
+ pixels: List[int] | List[List[int]],
34
+ pix_coor,
35
+ delta_window: float = 50e3,
36
+ ):
37
+ """Calculate timestamp differences for firmware version 2212.
38
+
39
+ Calculate timestamp differences for the given pixels and LinoSPAD2
40
+ firmware version 2212.
41
+
42
+ Parameters
43
+ ----------
44
+ data : list of array-like
45
+ List of data arrays, each corresponding to a different TDC.
46
+ pixels : List[int] | List[List[int]]
47
+ List of pixel numbers for which the timestamp differences should
48
+ be calculated or list of two lists with pixel numbers for peak
49
+ vs. peak calculations.
50
+ pix_coor : array-like
51
+ Array for transforming the pixel address in terms of TDC (0 to 3)
52
+ to pixel number in terms of half of the sensor (0 to 255).
53
+ delta_window : float, optional
54
+ Width of the time window for counting timestamp differences.
55
+ The default is 50e3 (50 ns).
56
+
57
+ Returns
58
+ -------
59
+ deltas_all : dict
60
+ Dictionary containing timestamp differences for each pair of pixels.
61
+
62
+ """
63
+
64
+ # TODO: remove
65
+ warn(
66
+ "This function is deprecated. Use" "'calculate_differences_2212_fast'",
67
+ DeprecationWarning,
68
+ stacklevel=2,
69
+ )
70
+ # Dictionary for the timestamp differences, where keys are the
71
+ # pixel numbers of the requested pairs
72
+ deltas_all = {}
73
+
74
+ pixels_left, pixels_right = utils.pixel_list_transform(pixels)
75
+
76
+ # Find ends of cycles
77
+ cycle_ends = np.argwhere(data[0].T[0] == -2)
78
+ cycle_ends = np.insert(cycle_ends, 0, 0)
79
+
80
+ for q in pixels_left:
81
+ # First pixel in the pair
82
+ tdc1, pix_c1 = np.argwhere(pix_coor == q)[0]
83
+ pix1 = np.where(data[tdc1].T[0] == pix_c1)[0]
84
+ for w in pixels_right:
85
+ if w <= q:
86
+ continue
87
+ deltas_all[f"{q},{w}"] = []
88
+
89
+ # Second pixel in the pair
90
+ tdc2, pix_c2 = np.argwhere(pix_coor == w)[0]
91
+ pix2 = np.where(data[tdc2].T[0] == pix_c2)[0]
92
+
93
+ # Go over cycles, getting data for the appropriate cycle
94
+ # only
95
+ for cyc in range(len(cycle_ends) - 1):
96
+ slice_from = cycle_ends[cyc]
97
+ slice_to = cycle_ends[cyc + 1]
98
+ pix1_slice = pix1[(pix1 >= slice_from) & (pix1 < slice_to)]
99
+ if not np.any(pix1_slice):
100
+ continue
101
+ pix2_slice = pix2[(pix2 >= slice_from) & (pix2 < slice_to)]
102
+ if not np.any(pix2_slice):
103
+ continue
104
+
105
+ # Calculate delta t
106
+ tmsp1 = data[tdc1].T[1][pix1_slice]
107
+ tmsp1 = tmsp1[tmsp1 > 0]
108
+ tmsp2 = data[tdc2].T[1][pix2_slice]
109
+ tmsp2 = tmsp2[tmsp2 > 0]
110
+ for t1 in tmsp1:
111
+ deltas = tmsp2 - t1
112
+ ind = np.where(np.abs(deltas) < delta_window)[0]
113
+ deltas_all[f"{q},{w}"].extend(deltas[ind])
114
+
115
+ return deltas_all
116
+
117
+
118
+ def calculate_differences_2212_fast(
119
+ data: ndarray,
120
+ pixels: List[int] | List[List[int]],
121
+ pix_coor: ndarray,
122
+ delta_window: float = 50e3,
123
+ cycle_length: float = 4e9,
124
+ ):
125
+ """Calculate timestamp differences for firmware version 2212.
126
+
127
+ Calculate timestamp differences for the given pixels and LinoSPAD2
128
+ firmware version 2212.
129
+
130
+ Parameters
131
+ ----------
132
+ data : ndarray
133
+ Matrix of timestamps, where rows correspond to the TDCs.
134
+ pixels : List[int] | List[List[int]]
135
+ List of pixel numbers for which the timestamp differences should
136
+ be calculated or list of two lists with pixel numbers for peak
137
+ vs. peak calculations.
138
+ pix_coor : ndarray
139
+ Array for transforming the pixel address in terms of TDC (0 to 3)
140
+ to pixel number in terms of half of the sensor (0 to 255).
141
+ delta_window : float, optional
142
+ Width of the time window for counting timestamp differences.
143
+ The default is 50e3 (50 ns).
144
+ cycle_length : float, optional
145
+ Length of each acquisition cycle. The default is 4e9 (4 ms).
146
+
147
+ Returns
148
+ -------
149
+ deltas_all : dict
150
+ Dictionary containing timestamp differences for each pair of pixels.
151
+
152
+ """
153
+
154
+ # Dictionary for the timestamp differences, where keys are the
155
+ # pixel numbers of the requested pairs
156
+ deltas_all = {}
157
+
158
+ pixels_left, pixels_right = utils.pixel_list_transform(pixels)
159
+
160
+ # Find ends of cycles
161
+ cycle_ends = np.argwhere(data[0].T[0] == -2)
162
+ cycle_ends = np.insert(cycle_ends, 0, 0)
163
+
164
+ for q in pixels_left:
165
+ # First pixel in the pair
166
+ tdc1, pix_c1 = np.argwhere(pix_coor == q)[0]
167
+ pix1 = np.where(data[tdc1].T[0] == pix_c1)[0]
168
+ for w in pixels_right:
169
+ if w <= q:
170
+ continue
171
+ deltas_all[f"{q},{w}"] = []
172
+
173
+ timestamps_1 = []
174
+ timestamps_2 = []
175
+
176
+ # Second pixel in the pair
177
+ tdc2, pix_c2 = np.argwhere(pix_coor == w)[0]
178
+ pix2 = np.where(data[tdc2].T[0] == pix_c2)[0]
179
+
180
+ # Go over cycles, shifting the timestamps from each next
181
+ # cycle by lengths of cycles before (e.g., for the 4th cycle
182
+ # add 12 ms)
183
+ for i, _ in enumerate(cycle_ends[:-1]):
184
+ slice_from = cycle_ends[i]
185
+ slice_to = cycle_ends[i + 1]
186
+ pix1_slice = pix1[(pix1 >= slice_from) & (pix1 < slice_to)]
187
+ if not np.any(pix1_slice):
188
+ continue
189
+ pix2_slice = pix2[(pix2 >= slice_from) & (pix2 < slice_to)]
190
+ if not np.any(pix2_slice):
191
+ continue
192
+
193
+ # Shift timestamps by cycle length
194
+ tmsp1 = data[tdc1].T[1][pix1_slice]
195
+ tmsp1 = tmsp1[tmsp1 > 0]
196
+ tmsp1 = tmsp1 + cycle_length * i
197
+
198
+ tmsp2 = data[tdc2].T[1][pix2_slice]
199
+ tmsp2 = tmsp2[tmsp2 > 0]
200
+ tmsp2 = tmsp2 + cycle_length * i
201
+
202
+ timestamps_1.extend(tmsp1)
203
+ timestamps_2.extend(tmsp2)
204
+
205
+ timestamps_1 = np.array(timestamps_1)
206
+ timestamps_2 = np.array(timestamps_2)
207
+
208
+ # Indicators for each pixel: 0 for timestamps from one pixel
209
+ # 1 - from the other
210
+ pix1_ind = np.zeros(len(timestamps_1), dtype=np.int32)
211
+ pix2_ind = np.ones(len(timestamps_2), dtype=np.int32)
212
+
213
+ pix1_data = np.vstack((pix1_ind, timestamps_1))
214
+ pix2_data = np.vstack((pix2_ind, timestamps_2))
215
+
216
+ # Dataframe for each pixel with pixel indicator and
217
+ # timestamps
218
+ df1 = pd.DataFrame(
219
+ pix1_data.T, columns=["Pixel_index", "Timestamp"]
220
+ )
221
+ df2 = pd.DataFrame(
222
+ pix2_data.T, columns=["Pixel_index", "Timestamp"]
223
+ )
224
+
225
+ # Combine the two dataframes
226
+ df_combined = pd.concat((df1, df2), ignore_index=True)
227
+
228
+ # Sort the timestamps
229
+ df_combined.sort_values("Timestamp", inplace=True)
230
+
231
+ # Subtract pixel indicators of neighbors; values of 0
232
+ # correspond to timestamp differences for the same pixel
233
+ # '-1' and '1' - to differences from different pixels
234
+ df_combined["Pixel_index_diff"] = df_combined["Pixel_index"].diff()
235
+
236
+ # Calculate timestamp difference between neighbors
237
+ df_combined["Timestamp_diff"] = df_combined["Timestamp"].diff()
238
+
239
+ # Get the correct timestamp difference sign
240
+ df_combined["Timestamp_diff"] = (
241
+ df_combined["Timestamp_diff"] * df_combined["Pixel_index_diff"]
242
+ )
243
+
244
+ # Collect timestamp differences where timestamps are from
245
+ # different pixels
246
+ filtered_df = df_combined[
247
+ abs(df_combined["Pixel_index_diff"]) == 1
248
+ ]
249
+
250
+ # Save only timestamps differences in the requested window
251
+ delta_ts = filtered_df[
252
+ abs(filtered_df["Timestamp_diff"]) < delta_window
253
+ ]["Timestamp_diff"].values
254
+
255
+ deltas_all[f"{q},{w}"].extend(delta_ts)
256
+
257
+ return deltas_all
258
+
259
+
260
+ # TODO: remove, redo
261
+ def calculate_differences_2212_fast_mod(
262
+ data: ndarray,
263
+ pixels: List[int] | List[List[int]],
264
+ pix_coor: ndarray,
265
+ delta_window: float = 50e3,
266
+ cycle_length: float = 4e9,
267
+ ):
268
+ """Calculate timestamp differences for firmware version 2212.
269
+
270
+ Calculate timestamp differences for the given pixels and LinoSPAD2
271
+ firmware version 2212. Calculated only for the diagonal pixels, i.e.,
272
+ 1-1, 2-2, etc., and not for all pairs.
273
+
274
+ Parameters
275
+ ----------
276
+ data : ndarray
277
+ Matrix of timestamps, where rows correspond to the TDCs.
278
+ pixels : List[int] | List[List[int]]
279
+ List of pixel numbers for which the timestamp differences should
280
+ be calculated or list of two lists with pixel numbers for peak
281
+ vs. peak calculations.
282
+ pix_coor : ndarray
283
+ Array for transforming the pixel address in terms of TDC (0 to 3)
284
+ to pixel number in terms of half of the sensor (0 to 255).
285
+ delta_window : float, optional
286
+ Width of the time window for counting timestamp differences.
287
+ The default is 50e3 (50 ns).
288
+ cycle_length : float, optional
289
+ Length of each acquisition cycle. The default is 4e9 (4 ms).
290
+
291
+ Returns
292
+ -------
293
+ deltas_all : dict
294
+ Dictionary containing timestamp differences for each pair of pixels.
295
+
296
+ """
297
+
298
+ # Dictionary for the timestamp differences, where keys are the
299
+ # pixel numbers of the requested pairs
300
+ deltas_all = {}
301
+
302
+ pixels_left, pixels_right = utils.pixel_list_transform(pixels)
303
+
304
+ if len(pixels_left) != len(pixels_right):
305
+ raise ValueError(
306
+ "The number of pixels from each peak should be the same."
307
+ )
308
+
309
+ # Find ends of cycles
310
+ cycle_ends = np.argwhere(data[0].T[0] == -2)
311
+ cycle_ends = np.insert(cycle_ends, 0, 0)
312
+
313
+ for i, _ in enumerate(pixels_left):
314
+ q = pixels_left[i]
315
+ w = pixels_right[i]
316
+ # First pixel in the pair
317
+ tdc1, pix_c1 = np.argwhere(pix_coor == q)[0]
318
+ pix1 = np.where(data[tdc1].T[0] == pix_c1)[0]
319
+ deltas_all[f"{q},{w}"] = []
320
+
321
+ timestamps_1 = []
322
+ timestamps_2 = []
323
+
324
+ # Second pixel in the pair
325
+ tdc2, pix_c2 = np.argwhere(pix_coor == w)[0]
326
+ pix2 = np.where(data[tdc2].T[0] == pix_c2)[0]
327
+
328
+ # Go over cycles, shifting the timestamps from each next
329
+ # cycle by lengths of cycles before (e.g., for the 4th cycle
330
+ # add 12 ms)
331
+ for i, _ in enumerate(cycle_ends[:-1]):
332
+ slice_from = cycle_ends[i]
333
+ slice_to = cycle_ends[i + 1]
334
+ pix1_slice = pix1[(pix1 >= slice_from) & (pix1 < slice_to)]
335
+ if not np.any(pix1_slice):
336
+ continue
337
+ pix2_slice = pix2[(pix2 >= slice_from) & (pix2 < slice_to)]
338
+ if not np.any(pix2_slice):
339
+ continue
340
+
341
+ # Shift timestamps by cycle length
342
+ tmsp1 = data[tdc1].T[1][pix1_slice]
343
+ tmsp1 = tmsp1[tmsp1 > 0]
344
+ tmsp1 = tmsp1 + cycle_length * i
345
+
346
+ tmsp2 = data[tdc2].T[1][pix2_slice]
347
+ tmsp2 = tmsp2[tmsp2 > 0]
348
+ tmsp2 = tmsp2 + cycle_length * i
349
+
350
+ timestamps_1.extend(tmsp1)
351
+ timestamps_2.extend(tmsp2)
352
+
353
+ timestamps_1 = np.array(timestamps_1)
354
+ timestamps_2 = np.array(timestamps_2)
355
+
356
+ # Indicators for each pixel: 0 for timestamps from one pixel
357
+ # 1 - from the other
358
+ pix1_ind = np.zeros(len(timestamps_1), dtype=np.int32)
359
+ pix2_ind = np.ones(len(timestamps_2), dtype=np.int32)
360
+
361
+ pix1_data = np.vstack((pix1_ind, timestamps_1))
362
+ pix2_data = np.vstack((pix2_ind, timestamps_2))
363
+
364
+ # Dataframe for each pixel with pixel indicator and
365
+ # timestamps
366
+ df1 = pd.DataFrame(pix1_data.T, columns=["Pixel_index", "Timestamp"])
367
+ df2 = pd.DataFrame(pix2_data.T, columns=["Pixel_index", "Timestamp"])
368
+
369
+ # Combine the two dataframes
370
+ df_combined = pd.concat((df1, df2), ignore_index=True)
371
+
372
+ # Sort the timestamps
373
+ df_combined.sort_values("Timestamp", inplace=True)
374
+
375
+ # Subtract pixel indicators of neighbors; values of 0
376
+ # correspond to timestamp differences for the same pixel
377
+ # '-1' and '1' - to differences from different pixels
378
+ df_combined["Pixel_index_diff"] = df_combined["Pixel_index"].diff()
379
+
380
+ # Calculate timestamp difference between neighbors
381
+ df_combined["Timestamp_diff"] = df_combined["Timestamp"].diff()
382
+
383
+ # Get the correct timestamp difference sign
384
+ df_combined["Timestamp_diff"] = (
385
+ df_combined["Timestamp_diff"] * df_combined["Pixel_index_diff"]
386
+ )
387
+
388
+ # Collect timestamp differences where timestamps are from
389
+ # different pixels
390
+ filtered_df = df_combined[abs(df_combined["Pixel_index_diff"]) == 1]
391
+
392
+ # Save only timestamps differences in the requested window
393
+ delta_ts = filtered_df[
394
+ abs(filtered_df["Timestamp_diff"]) < delta_window
395
+ ]["Timestamp_diff"].values
396
+
397
+ deltas_all[f"{q},{w}"].extend(delta_ts)
398
+
399
+ return deltas_all