daplis 0.9.1__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.
- daplis-0.9.1/LICENSE +21 -0
- daplis-0.9.1/PKG-INFO +115 -0
- daplis-0.9.1/README.md +90 -0
- daplis-0.9.1/pyproject.toml +35 -0
- daplis-0.9.1/setup.cfg +4 -0
- daplis-0.9.1/src/LinoSPAD2/__init__.py +0 -0
- daplis-0.9.1/src/LinoSPAD2/functions/__init__.py +0 -0
- daplis-0.9.1/src/LinoSPAD2/functions/calc_diff.py +256 -0
- daplis-0.9.1/src/LinoSPAD2/functions/calibrate.py +1005 -0
- daplis-0.9.1/src/LinoSPAD2/functions/compact_share.py +514 -0
- daplis-0.9.1/src/LinoSPAD2/functions/cross_talk.py +1379 -0
- daplis-0.9.1/src/LinoSPAD2/functions/data_quality.py +843 -0
- daplis-0.9.1/src/LinoSPAD2/functions/delta_t.py +2073 -0
- daplis-0.9.1/src/LinoSPAD2/functions/fits.py +1306 -0
- daplis-0.9.1/src/LinoSPAD2/functions/mp_analysis.py +1110 -0
- daplis-0.9.1/src/LinoSPAD2/functions/sensor_plot.py +996 -0
- daplis-0.9.1/src/LinoSPAD2/functions/unpack.py +414 -0
- daplis-0.9.1/src/LinoSPAD2/functions/utils.py +432 -0
- daplis-0.9.1/src/daplis.egg-info/PKG-INFO +115 -0
- daplis-0.9.1/src/daplis.egg-info/SOURCES.txt +25 -0
- daplis-0.9.1/src/daplis.egg-info/dependency_links.txt +1 -0
- daplis-0.9.1/src/daplis.egg-info/requires.txt +8 -0
- daplis-0.9.1/src/daplis.egg-info/top_level.txt +1 -0
- daplis-0.9.1/tests/test_cross_talk.py +110 -0
- daplis-0.9.1/tests/test_delta_t.py +319 -0
- daplis-0.9.1/tests/test_plot_tmsp.py +86 -0
- daplis-0.9.1/tests/test_unpack.py +39 -0
daplis-0.9.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Sergei Kulkov
|
|
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.
|
daplis-0.9.1/PKG-INFO
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: daplis
|
|
3
|
+
Version: 0.9.1
|
|
4
|
+
Summary: Data Analysis Package for LInoSpad2
|
|
5
|
+
Author-email: Sergei Kulkov <sergei.kulkov23@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: timestamp,analysis,LinoSPAD2
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Requires-Python: >=3.8
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: lmfit>=0.9.1
|
|
18
|
+
Requires-Dist: matplotlib>=3.5.0
|
|
19
|
+
Requires-Dist: numpy>=1.22.4
|
|
20
|
+
Requires-Dist: pandas>=1.4.0
|
|
21
|
+
Requires-Dist: pyarrow>=17.0.0
|
|
22
|
+
Requires-Dist: scipy>=1.7.0
|
|
23
|
+
Requires-Dist: seaborn>=0.9.0
|
|
24
|
+
Requires-Dist: tqdm>=4.5.0
|
|
25
|
+
|
|
26
|
+
# LinoSPAD2
|
|
27
|
+
|
|
28
|
+
Package for unpacking and analyzing the binary data from LinoSPAD2.
|
|
29
|
+
|
|
30
|
+

|
|
31
|
+

|
|
32
|
+
|
|
33
|
+
## Introduction
|
|
34
|
+
|
|
35
|
+
This package was written for data analysis for LinoSPAD2, mainly for
|
|
36
|
+
analysis of the timestamp output. The key functions are ones for
|
|
37
|
+
unpacking the binary output of the detector that utilizes the numpy
|
|
38
|
+
Python library for quick unpacking of .dat files to matrices,
|
|
39
|
+
dictionaries, or data frames.
|
|
40
|
+
|
|
41
|
+
The "functions" folder holds all functions from unpacking to plotting
|
|
42
|
+
numerous types of graphs (pixel population, histograms of timestamp
|
|
43
|
+
differences, etc.)
|
|
44
|
+
|
|
45
|
+
The "params" folder holds masks (used to mask some of the noisiest
|
|
46
|
+
pixels) and calibration data (compensating for TDC nonlinearities and
|
|
47
|
+
offset) for LinoSPAD2 daughterboards "A5" and "NL11".
|
|
48
|
+
|
|
49
|
+
The "archive" folder is a collection of scripts for debugging, tests,
|
|
50
|
+
older versions of functions, etc.
|
|
51
|
+
|
|
52
|
+
Full documentation, including examples and full documentation of
|
|
53
|
+
modules and functions, can be found [here](https://rngkomorebi.github.io/LinoSPAD2/).
|
|
54
|
+
|
|
55
|
+
Some functions (mainly the plotting ones) save plots as pictures in the
|
|
56
|
+
.png format, creating a folder for the output in the same folder that
|
|
57
|
+
holds the data. Others (such as delta_t.py for collecting timestamp differences
|
|
58
|
+
in the given time window) save .csv files with the processed data for
|
|
59
|
+
easier and faster plotting.
|
|
60
|
+
|
|
61
|
+
Additionally, a standalone repo with an application for online plotting
|
|
62
|
+
of the sensor population can be found [here](https://github.com/rngKomorebi/LinoSPAD2-app).
|
|
63
|
+
|
|
64
|
+
## Installation and usage
|
|
65
|
+
|
|
66
|
+
To start using the package, one can download the whole repo. The 'main.py'
|
|
67
|
+
serves as the main hub for calling the functions. "requirements.txt"
|
|
68
|
+
collects all packages required for this project to run. One can create
|
|
69
|
+
an environment for this project either using conda or install the
|
|
70
|
+
necessary packages using pip (for creating virtual environments using pip
|
|
71
|
+
see [this](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/)):
|
|
72
|
+
```
|
|
73
|
+
pip install virtualenv
|
|
74
|
+
py -m venv PATH/TO/ENVIRONMENT/ENVIRONMENT_NAME
|
|
75
|
+
PATH/TO/ENVIRONMENT/ENVIRONMENT_NAME/Scripts/activate
|
|
76
|
+
cd PATH/TO/GITHUB/CODES/LinoSPAD2
|
|
77
|
+
pip install -r requirements.txt
|
|
78
|
+
```
|
|
79
|
+
or (recommended)
|
|
80
|
+
```
|
|
81
|
+
conda create --name NEW_ENVIRONMENT_NAME --file /PATH/TO/requirements.txt -c conda-forge
|
|
82
|
+
```
|
|
83
|
+
To install the package, first, switch to the created environment:
|
|
84
|
+
```
|
|
85
|
+
conda activate NEW_ENVIRONMENT_NAME
|
|
86
|
+
```
|
|
87
|
+
or
|
|
88
|
+
```
|
|
89
|
+
PATH/TO/ENVIRONMENT/ENVIRONMENT_NAME/Scripts/activate
|
|
90
|
+
```
|
|
91
|
+
and run
|
|
92
|
+
```
|
|
93
|
+
pip install -e .
|
|
94
|
+
```
|
|
95
|
+
that will install the local package LinoSPAD2. After that, you can
|
|
96
|
+
import all functions in your project:
|
|
97
|
+
```
|
|
98
|
+
from LinoSPAD2.functions import plot_tmsp, delta_t, fits
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## How to contribute
|
|
102
|
+
|
|
103
|
+
This repo consists of two branches: 'main' serves as the release version
|
|
104
|
+
of the package, tested, proven to be functional, and ready to use, while
|
|
105
|
+
the 'develop' branch serves as the main hub for testing new stuff. To
|
|
106
|
+
contribute, the best way would be to fork the 'develop' branch and
|
|
107
|
+
submit via pull requests. Everyone willing to contribute is kindly asked
|
|
108
|
+
to follow the [PEP 8](https://peps.python.org/pep-0008/) and
|
|
109
|
+
[PEP 257](https://peps.python.org/pep-0257/) conventions.
|
|
110
|
+
|
|
111
|
+
## License and contact info
|
|
112
|
+
|
|
113
|
+
This package is available under the MIT license. See LICENSE for more
|
|
114
|
+
information. If you'd like to contact me, the author, feel free to
|
|
115
|
+
write at sergei.kulkov23@gmail.com.
|
daplis-0.9.1/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# LinoSPAD2
|
|
2
|
+
|
|
3
|
+
Package for unpacking and analyzing the binary data from LinoSPAD2.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Introduction
|
|
9
|
+
|
|
10
|
+
This package was written for data analysis for LinoSPAD2, mainly for
|
|
11
|
+
analysis of the timestamp output. The key functions are ones for
|
|
12
|
+
unpacking the binary output of the detector that utilizes the numpy
|
|
13
|
+
Python library for quick unpacking of .dat files to matrices,
|
|
14
|
+
dictionaries, or data frames.
|
|
15
|
+
|
|
16
|
+
The "functions" folder holds all functions from unpacking to plotting
|
|
17
|
+
numerous types of graphs (pixel population, histograms of timestamp
|
|
18
|
+
differences, etc.)
|
|
19
|
+
|
|
20
|
+
The "params" folder holds masks (used to mask some of the noisiest
|
|
21
|
+
pixels) and calibration data (compensating for TDC nonlinearities and
|
|
22
|
+
offset) for LinoSPAD2 daughterboards "A5" and "NL11".
|
|
23
|
+
|
|
24
|
+
The "archive" folder is a collection of scripts for debugging, tests,
|
|
25
|
+
older versions of functions, etc.
|
|
26
|
+
|
|
27
|
+
Full documentation, including examples and full documentation of
|
|
28
|
+
modules and functions, can be found [here](https://rngkomorebi.github.io/LinoSPAD2/).
|
|
29
|
+
|
|
30
|
+
Some functions (mainly the plotting ones) save plots as pictures in the
|
|
31
|
+
.png format, creating a folder for the output in the same folder that
|
|
32
|
+
holds the data. Others (such as delta_t.py for collecting timestamp differences
|
|
33
|
+
in the given time window) save .csv files with the processed data for
|
|
34
|
+
easier and faster plotting.
|
|
35
|
+
|
|
36
|
+
Additionally, a standalone repo with an application for online plotting
|
|
37
|
+
of the sensor population can be found [here](https://github.com/rngKomorebi/LinoSPAD2-app).
|
|
38
|
+
|
|
39
|
+
## Installation and usage
|
|
40
|
+
|
|
41
|
+
To start using the package, one can download the whole repo. The 'main.py'
|
|
42
|
+
serves as the main hub for calling the functions. "requirements.txt"
|
|
43
|
+
collects all packages required for this project to run. One can create
|
|
44
|
+
an environment for this project either using conda or install the
|
|
45
|
+
necessary packages using pip (for creating virtual environments using pip
|
|
46
|
+
see [this](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/)):
|
|
47
|
+
```
|
|
48
|
+
pip install virtualenv
|
|
49
|
+
py -m venv PATH/TO/ENVIRONMENT/ENVIRONMENT_NAME
|
|
50
|
+
PATH/TO/ENVIRONMENT/ENVIRONMENT_NAME/Scripts/activate
|
|
51
|
+
cd PATH/TO/GITHUB/CODES/LinoSPAD2
|
|
52
|
+
pip install -r requirements.txt
|
|
53
|
+
```
|
|
54
|
+
or (recommended)
|
|
55
|
+
```
|
|
56
|
+
conda create --name NEW_ENVIRONMENT_NAME --file /PATH/TO/requirements.txt -c conda-forge
|
|
57
|
+
```
|
|
58
|
+
To install the package, first, switch to the created environment:
|
|
59
|
+
```
|
|
60
|
+
conda activate NEW_ENVIRONMENT_NAME
|
|
61
|
+
```
|
|
62
|
+
or
|
|
63
|
+
```
|
|
64
|
+
PATH/TO/ENVIRONMENT/ENVIRONMENT_NAME/Scripts/activate
|
|
65
|
+
```
|
|
66
|
+
and run
|
|
67
|
+
```
|
|
68
|
+
pip install -e .
|
|
69
|
+
```
|
|
70
|
+
that will install the local package LinoSPAD2. After that, you can
|
|
71
|
+
import all functions in your project:
|
|
72
|
+
```
|
|
73
|
+
from LinoSPAD2.functions import plot_tmsp, delta_t, fits
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## How to contribute
|
|
77
|
+
|
|
78
|
+
This repo consists of two branches: 'main' serves as the release version
|
|
79
|
+
of the package, tested, proven to be functional, and ready to use, while
|
|
80
|
+
the 'develop' branch serves as the main hub for testing new stuff. To
|
|
81
|
+
contribute, the best way would be to fork the 'develop' branch and
|
|
82
|
+
submit via pull requests. Everyone willing to contribute is kindly asked
|
|
83
|
+
to follow the [PEP 8](https://peps.python.org/pep-0008/) and
|
|
84
|
+
[PEP 257](https://peps.python.org/pep-0257/) conventions.
|
|
85
|
+
|
|
86
|
+
## License and contact info
|
|
87
|
+
|
|
88
|
+
This package is available under the MIT license. See LICENSE for more
|
|
89
|
+
information. If you'd like to contact me, the author, feel free to
|
|
90
|
+
write at sergei.kulkov23@gmail.com.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "daplis"
|
|
7
|
+
version = "0.9.1"
|
|
8
|
+
description = "Data Analysis Package for LInoSpad2"
|
|
9
|
+
authors = [{ name = "Sergei Kulkov", email = "sergei.kulkov23@gmail.com" }]
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
requires-python = ">=3.8"
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Programming Language :: Python :: 3.8",
|
|
15
|
+
"Programming Language :: Python :: 3.9",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
]
|
|
21
|
+
keywords = ["timestamp", "analysis", "LinoSPAD2"]
|
|
22
|
+
|
|
23
|
+
dependencies = [
|
|
24
|
+
"lmfit>=0.9.1",
|
|
25
|
+
"matplotlib>=3.5.0",
|
|
26
|
+
"numpy>=1.22.4",
|
|
27
|
+
"pandas>=1.4.0",
|
|
28
|
+
"pyarrow>=17.0.0",
|
|
29
|
+
"scipy>=1.7.0",
|
|
30
|
+
"seaborn>=0.9.0",
|
|
31
|
+
"tqdm>=4.5.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.packages.find]
|
|
35
|
+
where = ["src"]
|
daplis-0.9.1/setup.cfg
ADDED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,256 @@
|
|
|
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 LinoSPAD2.functions import utils
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def calculate_differences_2212(
|
|
31
|
+
data: List[float],
|
|
32
|
+
pixels: List[int] | List[List[int]],
|
|
33
|
+
pix_coor,
|
|
34
|
+
delta_window: float = 50e3,
|
|
35
|
+
):
|
|
36
|
+
"""Calculate timestamp differences for firmware version 2212.
|
|
37
|
+
|
|
38
|
+
Calculate timestamp differences for the given pixels and LinoSPAD2
|
|
39
|
+
firmware version 2212.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
data : list of array-like
|
|
44
|
+
List of data arrays, each corresponding to a different TDC.
|
|
45
|
+
pixels : List[int] | List[List[int]]
|
|
46
|
+
List of pixel numbers for which the timestamp differences should
|
|
47
|
+
be calculated or list of two lists with pixel numbers for peak
|
|
48
|
+
vs. peak calculations.
|
|
49
|
+
pix_coor : array-like
|
|
50
|
+
Array for transforming the pixel address in terms of TDC (0 to 3)
|
|
51
|
+
to pixel number in terms of half of the sensor (0 to 255).
|
|
52
|
+
delta_window : float, optional
|
|
53
|
+
Width of the time window for counting timestamp differences.
|
|
54
|
+
The default is 50e3 (50 ns).
|
|
55
|
+
|
|
56
|
+
Returns
|
|
57
|
+
-------
|
|
58
|
+
deltas_all : dict
|
|
59
|
+
Dictionary containing timestamp differences for each pair of pixels.
|
|
60
|
+
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
# TODO: remove
|
|
64
|
+
warn(
|
|
65
|
+
"This function is deprecated. Use" "'calculate_differences_2212_fast'",
|
|
66
|
+
DeprecationWarning,
|
|
67
|
+
stacklevel=2,
|
|
68
|
+
)
|
|
69
|
+
# Dictionary for the timestamp differences, where keys are the
|
|
70
|
+
# pixel numbers of the requested pairs
|
|
71
|
+
deltas_all = {}
|
|
72
|
+
|
|
73
|
+
pixels_left, pixels_right = utils.pixel_list_transform(pixels)
|
|
74
|
+
|
|
75
|
+
# Find ends of cycles
|
|
76
|
+
cycle_ends = np.argwhere(data[0].T[0] == -2)
|
|
77
|
+
cycle_ends = np.insert(cycle_ends, 0, 0)
|
|
78
|
+
|
|
79
|
+
for q in pixels_left:
|
|
80
|
+
# First pixel in the pair
|
|
81
|
+
tdc1, pix_c1 = np.argwhere(pix_coor == q)[0]
|
|
82
|
+
pix1 = np.where(data[tdc1].T[0] == pix_c1)[0]
|
|
83
|
+
for w in pixels_right:
|
|
84
|
+
if w <= q:
|
|
85
|
+
continue
|
|
86
|
+
deltas_all[f"{q},{w}"] = []
|
|
87
|
+
|
|
88
|
+
# Second pixel in the pair
|
|
89
|
+
tdc2, pix_c2 = np.argwhere(pix_coor == w)[0]
|
|
90
|
+
pix2 = np.where(data[tdc2].T[0] == pix_c2)[0]
|
|
91
|
+
|
|
92
|
+
# Go over cycles, getting data for the appropriate cycle
|
|
93
|
+
# only
|
|
94
|
+
for cyc in range(len(cycle_ends) - 1):
|
|
95
|
+
slice_from = cycle_ends[cyc]
|
|
96
|
+
slice_to = cycle_ends[cyc + 1]
|
|
97
|
+
pix1_slice = pix1[(pix1 >= slice_from) & (pix1 < slice_to)]
|
|
98
|
+
if not np.any(pix1_slice):
|
|
99
|
+
continue
|
|
100
|
+
pix2_slice = pix2[(pix2 >= slice_from) & (pix2 < slice_to)]
|
|
101
|
+
if not np.any(pix2_slice):
|
|
102
|
+
continue
|
|
103
|
+
|
|
104
|
+
# Calculate delta t
|
|
105
|
+
tmsp1 = data[tdc1].T[1][pix1_slice]
|
|
106
|
+
tmsp1 = tmsp1[tmsp1 > 0]
|
|
107
|
+
tmsp2 = data[tdc2].T[1][pix2_slice]
|
|
108
|
+
tmsp2 = tmsp2[tmsp2 > 0]
|
|
109
|
+
for t1 in tmsp1:
|
|
110
|
+
deltas = tmsp2 - t1
|
|
111
|
+
ind = np.where(np.abs(deltas) < delta_window)[0]
|
|
112
|
+
deltas_all[f"{q},{w}"].extend(deltas[ind])
|
|
113
|
+
|
|
114
|
+
return deltas_all
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def calculate_differences_2212_fast(
|
|
118
|
+
data: ndarray,
|
|
119
|
+
pixels: List[int] | List[List[int]],
|
|
120
|
+
pix_coor: ndarray,
|
|
121
|
+
delta_window: float = 50e3,
|
|
122
|
+
cycle_length: float = 4e9,
|
|
123
|
+
):
|
|
124
|
+
"""Calculate timestamp differences for firmware version 2212.
|
|
125
|
+
|
|
126
|
+
Calculate timestamp differences for the given pixels and LinoSPAD2
|
|
127
|
+
firmware version 2212.
|
|
128
|
+
|
|
129
|
+
Parameters
|
|
130
|
+
----------
|
|
131
|
+
data : ndarray
|
|
132
|
+
Matrix of timestamps, where rows correspond to the TDCs.
|
|
133
|
+
pixels : List[int] | List[List[int]]
|
|
134
|
+
List of pixel numbers for which the timestamp differences should
|
|
135
|
+
be calculated or list of two lists with pixel numbers for peak
|
|
136
|
+
vs. peak calculations.
|
|
137
|
+
pix_coor : ndarray
|
|
138
|
+
Array for transforming the pixel address in terms of TDC (0 to 3)
|
|
139
|
+
to pixel number in terms of half of the sensor (0 to 255).
|
|
140
|
+
delta_window : float, optional
|
|
141
|
+
Width of the time window for counting timestamp differences.
|
|
142
|
+
The default is 50e3 (50 ns).
|
|
143
|
+
cycle_length : float, optional
|
|
144
|
+
Length of each acquisition cycle. The default is 4e9 (4 ms).
|
|
145
|
+
|
|
146
|
+
Returns
|
|
147
|
+
-------
|
|
148
|
+
deltas_all : dict
|
|
149
|
+
Dictionary containing timestamp differences for each pair of pixels.
|
|
150
|
+
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
# Dictionary for the timestamp differences, where keys are the
|
|
154
|
+
# pixel numbers of the requested pairs
|
|
155
|
+
deltas_all = {}
|
|
156
|
+
|
|
157
|
+
pixels_left, pixels_right = utils.pixel_list_transform(pixels)
|
|
158
|
+
|
|
159
|
+
# Find ends of cycles
|
|
160
|
+
cycle_ends = np.argwhere(data[0].T[0] == -2)
|
|
161
|
+
cycle_ends = np.insert(cycle_ends, 0, 0)
|
|
162
|
+
|
|
163
|
+
for q in pixels_left:
|
|
164
|
+
# First pixel in the pair
|
|
165
|
+
tdc1, pix_c1 = np.argwhere(pix_coor == q)[0]
|
|
166
|
+
pix1 = np.where(data[tdc1].T[0] == pix_c1)[0]
|
|
167
|
+
for w in pixels_right:
|
|
168
|
+
if w <= q:
|
|
169
|
+
continue
|
|
170
|
+
deltas_all[f"{q},{w}"] = []
|
|
171
|
+
|
|
172
|
+
timestamps_1 = []
|
|
173
|
+
timestamps_2 = []
|
|
174
|
+
|
|
175
|
+
# Second pixel in the pair
|
|
176
|
+
tdc2, pix_c2 = np.argwhere(pix_coor == w)[0]
|
|
177
|
+
pix2 = np.where(data[tdc2].T[0] == pix_c2)[0]
|
|
178
|
+
|
|
179
|
+
# Go over cycles, shifting the timestamps from each next
|
|
180
|
+
# cycle by lengths of cycles before (e.g., for the 4th cycle
|
|
181
|
+
# add 12 ms)
|
|
182
|
+
for i, _ in enumerate(cycle_ends[:-1]):
|
|
183
|
+
slice_from = cycle_ends[i]
|
|
184
|
+
slice_to = cycle_ends[i + 1]
|
|
185
|
+
pix1_slice = pix1[(pix1 >= slice_from) & (pix1 < slice_to)]
|
|
186
|
+
if not np.any(pix1_slice):
|
|
187
|
+
continue
|
|
188
|
+
pix2_slice = pix2[(pix2 >= slice_from) & (pix2 < slice_to)]
|
|
189
|
+
if not np.any(pix2_slice):
|
|
190
|
+
continue
|
|
191
|
+
|
|
192
|
+
# Shift timestamps by cycle length
|
|
193
|
+
tmsp1 = data[tdc1].T[1][pix1_slice]
|
|
194
|
+
tmsp1 = tmsp1[tmsp1 > 0]
|
|
195
|
+
tmsp1 = tmsp1 + cycle_length * i
|
|
196
|
+
|
|
197
|
+
tmsp2 = data[tdc2].T[1][pix2_slice]
|
|
198
|
+
tmsp2 = tmsp2[tmsp2 > 0]
|
|
199
|
+
tmsp2 = tmsp2 + cycle_length * i
|
|
200
|
+
|
|
201
|
+
timestamps_1.extend(tmsp1)
|
|
202
|
+
timestamps_2.extend(tmsp2)
|
|
203
|
+
|
|
204
|
+
timestamps_1 = np.array(timestamps_1)
|
|
205
|
+
timestamps_2 = np.array(timestamps_2)
|
|
206
|
+
|
|
207
|
+
# Indicators for each pixel: 0 for timestamps from one pixel
|
|
208
|
+
# 1 - from the other
|
|
209
|
+
pix1_ind = np.zeros(len(timestamps_1), dtype=np.int32)
|
|
210
|
+
pix2_ind = np.ones(len(timestamps_2), dtype=np.int32)
|
|
211
|
+
|
|
212
|
+
pix1_data = np.vstack((pix1_ind, timestamps_1))
|
|
213
|
+
pix2_data = np.vstack((pix2_ind, timestamps_2))
|
|
214
|
+
|
|
215
|
+
# Dataframe for each pixel with pixel indicator and
|
|
216
|
+
# timestamps
|
|
217
|
+
df1 = pd.DataFrame(
|
|
218
|
+
pix1_data.T, columns=["Pixel_index", "Timestamp"]
|
|
219
|
+
)
|
|
220
|
+
df2 = pd.DataFrame(
|
|
221
|
+
pix2_data.T, columns=["Pixel_index", "Timestamp"]
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
# Combine the two dataframes
|
|
225
|
+
df_combined = pd.concat((df1, df2), ignore_index=True)
|
|
226
|
+
|
|
227
|
+
# Sort the timestamps
|
|
228
|
+
df_combined.sort_values("Timestamp", inplace=True)
|
|
229
|
+
|
|
230
|
+
# Subtract pixel indicators of neighbors; values of 0
|
|
231
|
+
# correspond to timestamp differences for the same pixel
|
|
232
|
+
# '-1' and '1' - to differences from different pixels
|
|
233
|
+
df_combined["Pixel_index_diff"] = df_combined["Pixel_index"].diff()
|
|
234
|
+
|
|
235
|
+
# Calculate timestamp difference between neighbors
|
|
236
|
+
df_combined["Timestamp_diff"] = df_combined["Timestamp"].diff()
|
|
237
|
+
|
|
238
|
+
# Get the correct timestamp difference sign
|
|
239
|
+
df_combined["Timestamp_diff"] = (
|
|
240
|
+
df_combined["Timestamp_diff"] * df_combined["Pixel_index_diff"]
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# Collect timestamp differences where timestamps are from
|
|
244
|
+
# different pixels
|
|
245
|
+
filtered_df = df_combined[
|
|
246
|
+
abs(df_combined["Pixel_index_diff"]) == 1
|
|
247
|
+
]
|
|
248
|
+
|
|
249
|
+
# Save only timestamps differences in the requested window
|
|
250
|
+
delta_ts = filtered_df[
|
|
251
|
+
abs(filtered_df["Timestamp_diff"]) < delta_window
|
|
252
|
+
]["Timestamp_diff"].values
|
|
253
|
+
|
|
254
|
+
deltas_all[f"{q},{w}"].extend(delta_ts)
|
|
255
|
+
|
|
256
|
+
return deltas_all
|