readerbotda 1.3.2__tar.gz → 1.4.0__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.
- {readerbotda-1.3.2 → readerbotda-1.4.0}/PKG-INFO +27 -10
- {readerbotda-1.3.2 → readerbotda-1.4.0}/README.md +24 -9
- readerbotda-1.4.0/ReaderBOTDA/reader.py +389 -0
- readerbotda-1.4.0/ReaderBOTDA/script.py +66 -0
- {readerbotda-1.3.2 → readerbotda-1.4.0}/pyproject.toml +8 -3
- readerbotda-1.3.2/ReaderBOTDA/reader.py +0 -261
- {readerbotda-1.3.2 → readerbotda-1.4.0}/ReaderBOTDA/__init__.py +0 -0
- {readerbotda-1.3.2 → readerbotda-1.4.0}/ReaderBOTDA/converter.py +0 -0
- {readerbotda-1.3.2 → readerbotda-1.4.0}/ReaderBOTDA/plotter/__init__.py +0 -0
- {readerbotda-1.3.2 → readerbotda-1.4.0}/ReaderBOTDA/plotter/abc.py +0 -0
- {readerbotda-1.3.2 → readerbotda-1.4.0}/ReaderBOTDA/plotter/bokeh.py +0 -0
- {readerbotda-1.3.2 → readerbotda-1.4.0}/ReaderBOTDA/plotter/plotly.py +0 -0
- {readerbotda-1.3.2 → readerbotda-1.4.0}/ReaderBOTDA/settings.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: readerbotda
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: Pacchetto per lettura e visualizzazione file di log sensore BOTDA Cohaerentia
|
|
5
5
|
Author: Marco Brunero
|
|
6
6
|
Author-email: marco.brunero@cohaerentia.com
|
|
@@ -11,6 +11,8 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.13
|
|
12
12
|
Requires-Dist: bokeh (>=3.7.2,<4.0.0)
|
|
13
13
|
Requires-Dist: dacite (>=1.9.2,<2.0.0)
|
|
14
|
+
Requires-Dist: h5py (>=3.14.0,<4.0.0)
|
|
15
|
+
Requires-Dist: nbformat (>=5.10.4,<6.0.0)
|
|
14
16
|
Requires-Dist: numpy (>=2.2.4,<3.0.0)
|
|
15
17
|
Requires-Dist: plotly (>=6.0.1,<7.0.0)
|
|
16
18
|
Requires-Dist: progress (>=1.6,<2.0)
|
|
@@ -23,16 +25,12 @@ Pacchetto per lettura e visualizzazione delle misure salvate da software per sen
|
|
|
23
25
|
|
|
24
26
|
## Installazione
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
Tramite `pip`:
|
|
27
29
|
|
|
28
30
|
```bash
|
|
29
|
-
pip install
|
|
31
|
+
pip install readerbotda
|
|
30
32
|
```
|
|
31
33
|
|
|
32
|
-
In questo modo i files dovrebbero essere ancora editabili e la versione installata dovrebbe automaticamente aggiornarsi. Nota bene: se si sta usando un notebook, è necessario riavviare il kernel, non è sufficiente re importare il pacchetto.
|
|
33
|
-
|
|
34
|
-
Dovrebbe anche essere possibile installare direttamente tramite link al repository privato ma devo ancora guardare come.
|
|
35
|
-
|
|
36
34
|
## Utilizzo
|
|
37
35
|
|
|
38
36
|
Per prima cosa è necessario caricare il necessario dai due moduli di lettura e visualizzazione:
|
|
@@ -56,7 +54,7 @@ L'idea è che chiunque potrebbe creare una nuova classe parente della classe `Pl
|
|
|
56
54
|
|
|
57
55
|
### Misura Singola
|
|
58
56
|
|
|
59
|
-
Lettura di singola misura da un singolo file "profilo".
|
|
57
|
+
Lettura di singola misura da un singolo file "profilo" di tipo json.
|
|
60
58
|
|
|
61
59
|
```python
|
|
62
60
|
misura = Profile('data/profiles/2021-11-08_16-51-16.652_rawarray.json',plotter=plotter)
|
|
@@ -68,7 +66,7 @@ fig.write_html("prova.html", full_html=False, include_plotlyjs='cdn')
|
|
|
68
66
|
|
|
69
67
|
### Misure multiple in una cartella
|
|
70
68
|
|
|
71
|
-
Lettura di tutti i file di tipo profilo in una cartella:
|
|
69
|
+
Lettura di tutti i file di tipo profilo in una cartella, contenente files di tipo json:
|
|
72
70
|
|
|
73
71
|
```python
|
|
74
72
|
from datetime import datetime
|
|
@@ -123,7 +121,7 @@ Si utilizza la funzione [`np.corrcoef`](https://numpy.org/doc/stable/reference/g
|
|
|
123
121
|
|
|
124
122
|
### Misura Raw
|
|
125
123
|
|
|
126
|
-
Lettura di file di debug che contiene intera matrice BGS e test dei metodi disponibili.
|
|
124
|
+
Lettura di file json di debug che contiene intera matrice BGS e test dei metodi disponibili.
|
|
127
125
|
|
|
128
126
|
```python
|
|
129
127
|
raw = Raw(filename='data/raw/2021-11-08_16-51-16.652_rawmatrix.json', plotter=plotter)
|
|
@@ -139,6 +137,18 @@ fig = raw.plotBGS(index=125)
|
|
|
139
137
|
plotter.show(fig)
|
|
140
138
|
```
|
|
141
139
|
|
|
140
|
+
## Lettura di misure in singolo file H5
|
|
141
|
+
|
|
142
|
+
Per leggere misure salvate in un file H5, è possibile utilizzare la classe `h5Profile`:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from ReaderBOTDA.reader import h5Profile
|
|
146
|
+
|
|
147
|
+
h5 = h5Profile('data/2023_09/build1.3_profile.h5', plotter=plotter)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
A questo punto l'oggetto `h5Profile` si dovrebbe comportare come `multipleProfile`, quindi è possibile utilizzare i metodi `plot()`, `calcStatistics()`, `calcCorrelations()` e così via.
|
|
151
|
+
|
|
142
152
|
## Plotter Bokeh
|
|
143
153
|
|
|
144
154
|
Oltre al plotter Plotly è disponibile anche una versione che utilizza il pacchetto `bokeh`. Non sono al momento disponibili i metodi `Bokeh.plot2d()` e `Bokeh.plot3d()`.
|
|
@@ -161,3 +171,10 @@ fig = misura.plot()
|
|
|
161
171
|
plotter.show(fig)
|
|
162
172
|
```
|
|
163
173
|
|
|
174
|
+
## TODO
|
|
175
|
+
|
|
176
|
+
1. lettura misure raw da file H5.
|
|
177
|
+
2. sistemare settings nelle ultime versioni di sw.
|
|
178
|
+
3. sistemare la timezone nelle misure.
|
|
179
|
+
4. aggiungere ricalcolo stima BFS a partire da dati raw.
|
|
180
|
+
|
|
@@ -4,16 +4,12 @@ Pacchetto per lettura e visualizzazione delle misure salvate da software per sen
|
|
|
4
4
|
|
|
5
5
|
## Installazione
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Tramite `pip`:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
pip install
|
|
10
|
+
pip install readerbotda
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
In questo modo i files dovrebbero essere ancora editabili e la versione installata dovrebbe automaticamente aggiornarsi. Nota bene: se si sta usando un notebook, è necessario riavviare il kernel, non è sufficiente re importare il pacchetto.
|
|
14
|
-
|
|
15
|
-
Dovrebbe anche essere possibile installare direttamente tramite link al repository privato ma devo ancora guardare come.
|
|
16
|
-
|
|
17
13
|
## Utilizzo
|
|
18
14
|
|
|
19
15
|
Per prima cosa è necessario caricare il necessario dai due moduli di lettura e visualizzazione:
|
|
@@ -37,7 +33,7 @@ L'idea è che chiunque potrebbe creare una nuova classe parente della classe `Pl
|
|
|
37
33
|
|
|
38
34
|
### Misura Singola
|
|
39
35
|
|
|
40
|
-
Lettura di singola misura da un singolo file "profilo".
|
|
36
|
+
Lettura di singola misura da un singolo file "profilo" di tipo json.
|
|
41
37
|
|
|
42
38
|
```python
|
|
43
39
|
misura = Profile('data/profiles/2021-11-08_16-51-16.652_rawarray.json',plotter=plotter)
|
|
@@ -49,7 +45,7 @@ fig.write_html("prova.html", full_html=False, include_plotlyjs='cdn')
|
|
|
49
45
|
|
|
50
46
|
### Misure multiple in una cartella
|
|
51
47
|
|
|
52
|
-
Lettura di tutti i file di tipo profilo in una cartella:
|
|
48
|
+
Lettura di tutti i file di tipo profilo in una cartella, contenente files di tipo json:
|
|
53
49
|
|
|
54
50
|
```python
|
|
55
51
|
from datetime import datetime
|
|
@@ -104,7 +100,7 @@ Si utilizza la funzione [`np.corrcoef`](https://numpy.org/doc/stable/reference/g
|
|
|
104
100
|
|
|
105
101
|
### Misura Raw
|
|
106
102
|
|
|
107
|
-
Lettura di file di debug che contiene intera matrice BGS e test dei metodi disponibili.
|
|
103
|
+
Lettura di file json di debug che contiene intera matrice BGS e test dei metodi disponibili.
|
|
108
104
|
|
|
109
105
|
```python
|
|
110
106
|
raw = Raw(filename='data/raw/2021-11-08_16-51-16.652_rawmatrix.json', plotter=plotter)
|
|
@@ -120,6 +116,18 @@ fig = raw.plotBGS(index=125)
|
|
|
120
116
|
plotter.show(fig)
|
|
121
117
|
```
|
|
122
118
|
|
|
119
|
+
## Lettura di misure in singolo file H5
|
|
120
|
+
|
|
121
|
+
Per leggere misure salvate in un file H5, è possibile utilizzare la classe `h5Profile`:
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from ReaderBOTDA.reader import h5Profile
|
|
125
|
+
|
|
126
|
+
h5 = h5Profile('data/2023_09/build1.3_profile.h5', plotter=plotter)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
A questo punto l'oggetto `h5Profile` si dovrebbe comportare come `multipleProfile`, quindi è possibile utilizzare i metodi `plot()`, `calcStatistics()`, `calcCorrelations()` e così via.
|
|
130
|
+
|
|
123
131
|
## Plotter Bokeh
|
|
124
132
|
|
|
125
133
|
Oltre al plotter Plotly è disponibile anche una versione che utilizza il pacchetto `bokeh`. Non sono al momento disponibili i metodi `Bokeh.plot2d()` e `Bokeh.plot3d()`.
|
|
@@ -141,3 +149,10 @@ misura = Profile('data/profiles/2021-11-08_16-51-16.652_rawarray.json',plotter=p
|
|
|
141
149
|
fig = misura.plot()
|
|
142
150
|
plotter.show(fig)
|
|
143
151
|
```
|
|
152
|
+
|
|
153
|
+
## TODO
|
|
154
|
+
|
|
155
|
+
1. lettura misure raw da file H5.
|
|
156
|
+
2. sistemare settings nelle ultime versioni di sw.
|
|
157
|
+
3. sistemare la timezone nelle misure.
|
|
158
|
+
4. aggiungere ricalcolo stima BFS a partire da dati raw.
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
from ReaderBOTDA.settings import parseSettingsDict, Settings
|
|
2
|
+
from ReaderBOTDA.plotter.abc import Plotter
|
|
3
|
+
from ReaderBOTDA.plotter.plotly import Plotly
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from json import load, loads
|
|
8
|
+
import numpy as np
|
|
9
|
+
import numpy.typing as npt
|
|
10
|
+
import h5py
|
|
11
|
+
from datetime import datetime, timezone # TODO usare numpy anche per questo?
|
|
12
|
+
from os import path, PathLike, strerror
|
|
13
|
+
from glob import glob
|
|
14
|
+
from typing import Tuple, Union, Literal
|
|
15
|
+
import errno
|
|
16
|
+
import warnings
|
|
17
|
+
from progress.bar import Bar
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class NoFilesSelected(Exception):
|
|
21
|
+
def __init__(self, folder, message="No file found in folder"):
|
|
22
|
+
self.message = f"{message}: {folder}"
|
|
23
|
+
super().__init__(self.message)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# TODO da implementare nei metodi. E aggiungere anche i campi MaxMean e MaxStd
|
|
27
|
+
@dataclass
|
|
28
|
+
class Statistics:
|
|
29
|
+
BFSmean: npt.ArrayLike
|
|
30
|
+
BFSstd: npt.ArrayLike
|
|
31
|
+
BFSstd_mean: float
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Profile:
|
|
35
|
+
|
|
36
|
+
filename: str = ""
|
|
37
|
+
plotter: Plotter
|
|
38
|
+
settings: Settings
|
|
39
|
+
sw_version: str = "<1.2.0.0"
|
|
40
|
+
BFS: np.ndarray = np.array([])
|
|
41
|
+
MaxGain: np.ndarray = np.array([])
|
|
42
|
+
timestamp: datetime = datetime.now
|
|
43
|
+
|
|
44
|
+
def __init__(
|
|
45
|
+
self, filename: PathLike, plotter: Plotter = Plotly(), name: str = None
|
|
46
|
+
) -> None:
|
|
47
|
+
"""Load a single measure from a json file."""
|
|
48
|
+
self.filename = filename
|
|
49
|
+
self.plotter = plotter
|
|
50
|
+
with open(self.filename) as file:
|
|
51
|
+
text = load(file)
|
|
52
|
+
self.settings = parseSettingsDict(text["Settings"])
|
|
53
|
+
if "sw_version" in text:
|
|
54
|
+
self.sw_version = text["sw_version"]
|
|
55
|
+
if "sw_version" in text and text["sw_version"] == "":
|
|
56
|
+
self.sw_version = "ambiente sviluppo"
|
|
57
|
+
self.timestamp = datetime.strptime(
|
|
58
|
+
text["Time Stamp"], "%Y-%m-%d" + "T" + "%H:%M:%S.%f" + "Z"
|
|
59
|
+
) # "2021-11-08T16:51:16.652Z"
|
|
60
|
+
if not name:
|
|
61
|
+
self.name = self.timestamp.strftime("%m/%d/%Y, %H:%M:%S")
|
|
62
|
+
else:
|
|
63
|
+
self.name = name
|
|
64
|
+
|
|
65
|
+
self.BFS = np.array(text["Profile"])
|
|
66
|
+
self._createPositionArray()
|
|
67
|
+
if "arrayMaxGain" in text:
|
|
68
|
+
self.MaxGain = np.array(text["arrayMaxGain"])
|
|
69
|
+
|
|
70
|
+
def _createPositionArray(self):
|
|
71
|
+
self.position = np.linspace(
|
|
72
|
+
0, self.settings.Cable.Length, num=len(self.BFS), endpoint=True
|
|
73
|
+
)
|
|
74
|
+
self.spatialResolution = self.position[1]
|
|
75
|
+
|
|
76
|
+
def plot(self, title: str = None):
|
|
77
|
+
if not title:
|
|
78
|
+
title = self.name
|
|
79
|
+
# TODO usare xrange espresso in metri per affettare array e poi passarli a single_plot. xrange:Tuple[float,float]=None
|
|
80
|
+
return self.plotter.single_plot(self.position, self.BFS, title=title)
|
|
81
|
+
|
|
82
|
+
def plotMax(self, title: str = None):
|
|
83
|
+
if self.MaxGain.size == 0:
|
|
84
|
+
warnings.warn(
|
|
85
|
+
"Max array in not available. If possibile, load the raw file of the same measure."
|
|
86
|
+
)
|
|
87
|
+
return None
|
|
88
|
+
if not title:
|
|
89
|
+
title = self.name
|
|
90
|
+
return self.plotter.max_plot(self.position, self.MaxGain, title)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class multipleProfile:
|
|
94
|
+
|
|
95
|
+
statistics: Statistics
|
|
96
|
+
plotter: Plotter
|
|
97
|
+
|
|
98
|
+
def __init__(
|
|
99
|
+
self,
|
|
100
|
+
folder: PathLike,
|
|
101
|
+
plotter: Plotter = Plotly(),
|
|
102
|
+
n_measure: int = None,
|
|
103
|
+
start_measure: Union[int, datetime] = 0,
|
|
104
|
+
stop_measure: datetime = None,
|
|
105
|
+
):
|
|
106
|
+
|
|
107
|
+
self.folder = folder
|
|
108
|
+
self.plotter = plotter
|
|
109
|
+
|
|
110
|
+
filelist = glob(path.join(folder, "*.json"))
|
|
111
|
+
if start_measure and isinstance(start_measure, datetime):
|
|
112
|
+
timestamps_files = [
|
|
113
|
+
datetime.strptime(
|
|
114
|
+
"_".join(path.basename(file).split("_")[:2]), "%Y-%m-%d_%H-%M-%S.%f"
|
|
115
|
+
)
|
|
116
|
+
for file in filelist
|
|
117
|
+
]
|
|
118
|
+
primo = next(
|
|
119
|
+
(
|
|
120
|
+
x
|
|
121
|
+
for x, value in enumerate(timestamps_files)
|
|
122
|
+
if value >= start_measure
|
|
123
|
+
),
|
|
124
|
+
0,
|
|
125
|
+
)
|
|
126
|
+
if stop_measure:
|
|
127
|
+
ultimo = next(
|
|
128
|
+
(
|
|
129
|
+
x
|
|
130
|
+
for x, value in enumerate(timestamps_files)
|
|
131
|
+
if value > stop_measure
|
|
132
|
+
),
|
|
133
|
+
len(filelist),
|
|
134
|
+
)
|
|
135
|
+
elif n_measure:
|
|
136
|
+
ultimo = primo + n_measure
|
|
137
|
+
else:
|
|
138
|
+
ultimo = len(filelist)
|
|
139
|
+
filelist = filelist[primo:ultimo]
|
|
140
|
+
|
|
141
|
+
if n_measure and (start_measure == 0 or isinstance(start_measure, int)):
|
|
142
|
+
filelist = filelist[start_measure : start_measure + n_measure]
|
|
143
|
+
|
|
144
|
+
if isinstance(start_measure, int) and not n_measure and stop_measure:
|
|
145
|
+
timestamps_files = [
|
|
146
|
+
datetime.strptime(
|
|
147
|
+
"_".join(path.basename(file).split("_")[:2]), "%Y-%m-%d_%H-%M-%S.%f"
|
|
148
|
+
)
|
|
149
|
+
for file in filelist
|
|
150
|
+
]
|
|
151
|
+
ultimo = next(
|
|
152
|
+
(x for x, value in enumerate(timestamps_files) if value > stop_measure),
|
|
153
|
+
len(filelist),
|
|
154
|
+
)
|
|
155
|
+
filelist = filelist[start_measure:ultimo]
|
|
156
|
+
|
|
157
|
+
if len(filelist) == 0:
|
|
158
|
+
raise NoFilesSelected(folder=folder)
|
|
159
|
+
|
|
160
|
+
timestamps = list()
|
|
161
|
+
with Bar("Redaing files", max=len(filelist)) as bar:
|
|
162
|
+
for file in filelist:
|
|
163
|
+
temp = Profile(filename=file)
|
|
164
|
+
timestamps.append(temp.timestamp)
|
|
165
|
+
try:
|
|
166
|
+
self.BFS = np.column_stack((self.BFS, temp.BFS))
|
|
167
|
+
self.MaxGain = np.column_stack((self.MaxGain, temp.MaxGain))
|
|
168
|
+
except AttributeError:
|
|
169
|
+
self.BFS = temp.BFS
|
|
170
|
+
self.MaxGain = temp.MaxGain
|
|
171
|
+
bar.next()
|
|
172
|
+
|
|
173
|
+
self.timestamps = np.array(timestamps)
|
|
174
|
+
self.settings = temp.settings
|
|
175
|
+
self.sw_version = temp.sw_version
|
|
176
|
+
self.position = temp.position
|
|
177
|
+
self.calcStatistics()
|
|
178
|
+
self.MaxGainMean = self.MaxGain.mean(axis=1)
|
|
179
|
+
self.MaxGainStd = self.MaxGain.std(axis=1)
|
|
180
|
+
|
|
181
|
+
def calcCorrelations(
|
|
182
|
+
self,
|
|
183
|
+
type: Literal["max", "bfs"],
|
|
184
|
+
reference: Literal["first", "previous"] = "previous",
|
|
185
|
+
range: Tuple[float, float] = None,
|
|
186
|
+
) -> np.array:
|
|
187
|
+
"""Ritorna correlazione tra prima misura e misura n-esima.
|
|
188
|
+
Si può scegliere se effettuarla su matrice dei BFS o matrice dei massimi"""
|
|
189
|
+
|
|
190
|
+
if type == "max":
|
|
191
|
+
correlations = np.corrcoef(
|
|
192
|
+
self.MaxGain[range[0] : range[1]] if range else self.MaxGain,
|
|
193
|
+
rowvar=False,
|
|
194
|
+
)
|
|
195
|
+
else:
|
|
196
|
+
correlations = np.corrcoef(
|
|
197
|
+
self.BFS[range[0] : range[1]] if range else self.BFS, rowvar=False
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
if reference == "first":
|
|
201
|
+
return correlations[0, :]
|
|
202
|
+
|
|
203
|
+
indici = np.arange(1, np.shape(correlations)[0])
|
|
204
|
+
return np.insert(correlations[indici, indici - 1], 0, 1)
|
|
205
|
+
|
|
206
|
+
def calcStatistics(
|
|
207
|
+
self, plot: bool = False, range: Tuple[float, float] = None, title: str = None
|
|
208
|
+
) -> Statistics:
|
|
209
|
+
# TODO gestione input range
|
|
210
|
+
self.statistics = Statistics(
|
|
211
|
+
BFSmean=self.BFS.mean(axis=1),
|
|
212
|
+
BFSstd=self.BFS.std(axis=1),
|
|
213
|
+
BFSstd_mean=self.BFS.std(axis=1).mean(),
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
if plot:
|
|
217
|
+
if not title:
|
|
218
|
+
title = self.folder
|
|
219
|
+
return self.plotter.statistics(
|
|
220
|
+
self.position,
|
|
221
|
+
self.statistics.BFSmean,
|
|
222
|
+
self.statistics.BFSstd,
|
|
223
|
+
title=title,
|
|
224
|
+
)
|
|
225
|
+
return self.statistics
|
|
226
|
+
|
|
227
|
+
def plotStatistics(self, title: str = None):
|
|
228
|
+
if not title:
|
|
229
|
+
title = self.folder
|
|
230
|
+
# TODO se sono state calcolate con range allora position è sbagliato
|
|
231
|
+
return self.plotter.statistics(
|
|
232
|
+
self.position, self.statistics.BFSmean, self.statistics.BFSstd, title=title
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
def plot(
|
|
236
|
+
self,
|
|
237
|
+
startTime: datetime = datetime.min,
|
|
238
|
+
stopTime: datetime = datetime.now(),
|
|
239
|
+
title: str = None,
|
|
240
|
+
):
|
|
241
|
+
if not title:
|
|
242
|
+
title = self.folder
|
|
243
|
+
match = [
|
|
244
|
+
i
|
|
245
|
+
for i, date in enumerate(self.timestamps)
|
|
246
|
+
if date >= startTime and date <= stopTime
|
|
247
|
+
]
|
|
248
|
+
return self.plotter.multiple_plot(
|
|
249
|
+
self.position,
|
|
250
|
+
self.BFS[:, match],
|
|
251
|
+
[self.timestamps[i] for i in match],
|
|
252
|
+
title=title,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
def plotMax(self, title: str = None):
|
|
256
|
+
if self.MaxGain.size == 0:
|
|
257
|
+
warnings.warn(
|
|
258
|
+
"Max array in not available. If possibile, load the raw file of the same measure."
|
|
259
|
+
)
|
|
260
|
+
return None
|
|
261
|
+
if not title:
|
|
262
|
+
title = self.folder
|
|
263
|
+
return self.plotter.max_stat_plot(self.MaxGainMean, self.MaxGainStd, title)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class h5Profile(multipleProfile):
|
|
267
|
+
|
|
268
|
+
def __init__(
|
|
269
|
+
self,
|
|
270
|
+
filename: PathLike,
|
|
271
|
+
plotter: Plotter = Plotly(),
|
|
272
|
+
# n_measure: int = None,
|
|
273
|
+
# start_measure: Union[int, datetime] = 0,
|
|
274
|
+
# stop_measure: datetime = None,
|
|
275
|
+
):
|
|
276
|
+
"""Load multiple measures from a h5 file."""
|
|
277
|
+
self.filename = filename
|
|
278
|
+
self.plotter = plotter
|
|
279
|
+
|
|
280
|
+
if not path.isfile(filename):
|
|
281
|
+
raise FileNotFoundError(errno.ENOENT, strerror(errno.ENOENT), filename)
|
|
282
|
+
|
|
283
|
+
with h5py.File(filename, "r") as f:
|
|
284
|
+
self.filename = filename
|
|
285
|
+
self.folder = f.attrs["folder"]
|
|
286
|
+
self.sw_version = f.attrs["sw_version"]
|
|
287
|
+
|
|
288
|
+
self.position = f["position"][:]
|
|
289
|
+
self.BFS = np.transpose(np.squeeze(f["data"]["bfs"][:]))
|
|
290
|
+
self.MaxGain = np.transpose(np.squeeze(f["data"]["max_gain"][:]))
|
|
291
|
+
self.timestamps = [
|
|
292
|
+
datetime.fromtimestamp(timestamp / 1000000) # FIXME, timezone.utc)
|
|
293
|
+
for timestamp in f["data"]["timestamps"][:]
|
|
294
|
+
]
|
|
295
|
+
self.settings = loads(
|
|
296
|
+
f.attrs["settings"]
|
|
297
|
+
) # FIXME parseSettingsDict(loads(f.attrs["settings"]))
|
|
298
|
+
|
|
299
|
+
self.calcStatistics()
|
|
300
|
+
self.MaxGainMean = self.MaxGain.mean(axis=1)
|
|
301
|
+
self.MaxGainStd = self.MaxGain.std(axis=1)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class Raw:
|
|
305
|
+
|
|
306
|
+
filename: PathLike = Path("")
|
|
307
|
+
plotter: Plotter
|
|
308
|
+
settings: Settings
|
|
309
|
+
sw_version: str = "<1.2.0.0"
|
|
310
|
+
BGS: np.ndarray = np.array([])
|
|
311
|
+
residuo: np.ndarray = np.array([])
|
|
312
|
+
timestamp: datetime = datetime.now
|
|
313
|
+
|
|
314
|
+
def __init__(self, filename: Union[str, Path], plotter: Plotter = Plotly()) -> None:
|
|
315
|
+
"""Load a single raw data from a json file."""
|
|
316
|
+
self.filename = filename
|
|
317
|
+
self.plotter = plotter
|
|
318
|
+
with open(self.filename) as file:
|
|
319
|
+
text = load(file)
|
|
320
|
+
self.settings = parseSettingsDict(text["Settings"])
|
|
321
|
+
if "sw_version" in text:
|
|
322
|
+
self.sw_version = text["sw_version"]
|
|
323
|
+
if "sw_version" in text and text["sw_version"] == "":
|
|
324
|
+
self.sw_version = "ambiente sviluppo"
|
|
325
|
+
self.BGS = np.transpose(np.array(text["Raw"]))
|
|
326
|
+
self.timestamp = datetime.strptime(
|
|
327
|
+
text["Time Stamp"], "%Y-%m-%d" + "T" + "%H:%M:%S.%f" + "Z"
|
|
328
|
+
) # "2021-11-08T16:51:16.652Z"
|
|
329
|
+
self._createPositionArray()
|
|
330
|
+
self._createFrequencyArray()
|
|
331
|
+
try:
|
|
332
|
+
self.residuo = np.array(text["residuo"])
|
|
333
|
+
except KeyError:
|
|
334
|
+
self.residuo = np.zeros(np.shape(self.frequency))
|
|
335
|
+
|
|
336
|
+
def _createPositionArray(self) -> None:
|
|
337
|
+
"""Crea array numpy delle posizioni e la risoluzione spaziale"""
|
|
338
|
+
self.position = np.linspace(
|
|
339
|
+
0, self.settings.Cable.Length, num=self.BGS.shape[1], endpoint=True
|
|
340
|
+
)
|
|
341
|
+
self.spatialResolution = self.position[1]
|
|
342
|
+
|
|
343
|
+
def _createFrequencyArray(self) -> None:
|
|
344
|
+
"""Crea array numpy delle frequenze, espresse in GHz"""
|
|
345
|
+
self.frequency = (
|
|
346
|
+
np.linspace(
|
|
347
|
+
self.settings.Clock.StartMHz,
|
|
348
|
+
self.settings.Clock.StartMHz
|
|
349
|
+
+ self.settings.Clock.StepMHz * self.BGS.shape[0],
|
|
350
|
+
num=self.BGS.shape[0],
|
|
351
|
+
endpoint=True,
|
|
352
|
+
)
|
|
353
|
+
/ 1000
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
def plot2d(self, title: str = None):
|
|
357
|
+
if not title:
|
|
358
|
+
title = self.filename
|
|
359
|
+
return self.plotter.raw2d_plot(
|
|
360
|
+
self.position, self.frequency, self.BGS, title=title
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
def plot3d(self, title: str = None):
|
|
364
|
+
if not title:
|
|
365
|
+
title = self.filename
|
|
366
|
+
return self.plotter.raw3d_plot(
|
|
367
|
+
self.position, self.frequency, self.BGS, title=title
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
def plotBGS(self, index: int = None, title: str = None):
|
|
371
|
+
"""Plot 2D di tutti gli spettri BGS"""
|
|
372
|
+
if not title:
|
|
373
|
+
title = self.filename
|
|
374
|
+
return self.plotter.rawBGS_plot(
|
|
375
|
+
self.frequency, self.BGS, index=index, title=title
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
def plotMax(self, title: str = None):
|
|
379
|
+
if not title:
|
|
380
|
+
title = self.filename
|
|
381
|
+
return self.plotter.max_plot(self.position, self.BGS.max(axis=0), title)
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
if __name__ == "__main__":
|
|
385
|
+
"""Non va se si lancia direttamente questo script a meno di non cambiare i primi due import da modules.settings a settings; uguale per plotter."""
|
|
386
|
+
# a = Profile(filename='data/profiles/2021-11-08_16-51-16.652_rawarray.json')
|
|
387
|
+
# b = multipleProfile(folder='data/profiles/')
|
|
388
|
+
c = Raw(filename="data/raw/2021-11-08_16-51-16.652_rawmatrix.json")
|
|
389
|
+
# print(b.BFS.shape)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#TODO trovare modo di integrarlo in setup.py di setuptools: https://typer.tiangolo.com/tutorial/package/
|
|
2
|
+
|
|
3
|
+
'''
|
|
4
|
+
Per help, digitare in terminale: python readBOTDA.py --help
|
|
5
|
+
e poi per help specifici su uno dei comandi: python readBOTDA.py multi --help
|
|
6
|
+
'''
|
|
7
|
+
|
|
8
|
+
import typer
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from ReaderBOTDA.reader import Profile, multipleProfile, Raw
|
|
11
|
+
from ReaderBOTDA.plotter.plotly import Plotly
|
|
12
|
+
from dataclasses import asdict
|
|
13
|
+
|
|
14
|
+
app = typer.Typer()
|
|
15
|
+
PLOTTER = Plotly(theme='plotly_dark')
|
|
16
|
+
|
|
17
|
+
@app.command()
|
|
18
|
+
def single(filename: str, title:str=None):
|
|
19
|
+
if not title:
|
|
20
|
+
title = filename
|
|
21
|
+
data = Profile(filename,PLOTTER)
|
|
22
|
+
PLOTTER.show(data.plot(title=title))
|
|
23
|
+
typer.secho("Settings:", fg=typer.colors.GREEN, bold=True)
|
|
24
|
+
typer.echo(str(data.settings))
|
|
25
|
+
|
|
26
|
+
@app.command()
|
|
27
|
+
def multi(folder: str, title: str =None, stat: bool = True):
|
|
28
|
+
if not title:
|
|
29
|
+
title = folder
|
|
30
|
+
data = multipleProfile(folder,PLOTTER)
|
|
31
|
+
typer.secho(f"Lette {len(data.timestamps)} misure nella cartella {folder}", fg=typer.colors.GREEN, bold=True)
|
|
32
|
+
PLOTTER.show(data.plot(title=title))
|
|
33
|
+
if stat:
|
|
34
|
+
PLOTTER.show(data.calcStatistics(plot=True,title=title))
|
|
35
|
+
typer.secho("Settings:", fg=typer.colors.GREEN, bold=True)
|
|
36
|
+
typer.echo(str(data.settings))
|
|
37
|
+
|
|
38
|
+
@app.command()
|
|
39
|
+
def raw(filename: str, title: str = None):
|
|
40
|
+
|
|
41
|
+
from plotly.subplots import make_subplots
|
|
42
|
+
if not title:
|
|
43
|
+
title = filename
|
|
44
|
+
|
|
45
|
+
data = Raw(filename, PLOTTER)
|
|
46
|
+
typer.secho("Settings:", fg=typer.colors.GREEN, bold=True)
|
|
47
|
+
typer.echo(str(data.settings))
|
|
48
|
+
|
|
49
|
+
fig2d = data.plot2d()
|
|
50
|
+
figMax = data.plotMax()
|
|
51
|
+
figBGS = data.plotBGS()
|
|
52
|
+
fig = make_subplots(rows=2, cols=2, shared_xaxes='columns', column_widths=[0.25, 0.75],row_heights=[0.75, 0.25])
|
|
53
|
+
|
|
54
|
+
fig.add_trace(fig2d.data[0], row=1, col=2)
|
|
55
|
+
fig.add_trace(figMax.data[0], row=2, col=2)
|
|
56
|
+
fig.add_traces(figBGS.data, rows=1, cols=1)
|
|
57
|
+
fig.update_xaxes(title_text='Position (m)',row=2,col=2)
|
|
58
|
+
fig.update_xaxes(title_text='Frequency (GHz)',row=1,col=1)
|
|
59
|
+
fig.update_yaxes(title_text='Frequency (GHz)',row=1,col=2)
|
|
60
|
+
fig.update_yaxes(title_text='Amplitude (V)',row=1,col=1)
|
|
61
|
+
fig.update_yaxes(title_text='Max Amp (V)',row=2,col=2)
|
|
62
|
+
fig.update_layout(title_text=title,showlegend=False)
|
|
63
|
+
fig.show()
|
|
64
|
+
|
|
65
|
+
if __name__ == "__main__":
|
|
66
|
+
app()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "readerbotda"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.4.0"
|
|
4
4
|
description = "Pacchetto per lettura e visualizzazione file di log sensore BOTDA Cohaerentia"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "Marco Brunero",email = "marco.brunero@cohaerentia.com"}
|
|
@@ -13,11 +13,16 @@ dependencies = [
|
|
|
13
13
|
"numpy (>=2.2.4,<3.0.0)",
|
|
14
14
|
"bokeh (>=3.7.2,<4.0.0)",
|
|
15
15
|
"typer (>=0.15.2,<0.16.0)",
|
|
16
|
-
"progress (>=1.6,<2.0)"
|
|
16
|
+
"progress (>=1.6,<2.0)",
|
|
17
|
+
"h5py (>=3.14.0,<4.0.0)",
|
|
18
|
+
"nbformat (>=5.10.4,<6.0.0)"
|
|
17
19
|
]
|
|
18
20
|
|
|
19
21
|
[tool.poetry.scripts]
|
|
20
|
-
|
|
22
|
+
readBOTDA = "ReaderBOTDA.script:app"
|
|
23
|
+
|
|
24
|
+
[tool.poetry.group.dev.dependencies]
|
|
25
|
+
ipykernel = "^6.29.5"
|
|
21
26
|
|
|
22
27
|
[build-system]
|
|
23
28
|
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
from ReaderBOTDA.settings import parseSettingsDict, Settings
|
|
2
|
-
from ReaderBOTDA.plotter.abc import Plotter
|
|
3
|
-
from ReaderBOTDA.plotter.plotly import Plotly
|
|
4
|
-
|
|
5
|
-
from dataclasses import dataclass
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from json import load
|
|
8
|
-
import numpy as np
|
|
9
|
-
from datetime import datetime # TODO usare numpy anche per questo?
|
|
10
|
-
from os import path
|
|
11
|
-
from glob import glob
|
|
12
|
-
from typing import Tuple, Union, Literal
|
|
13
|
-
import warnings
|
|
14
|
-
from progress.bar import Bar
|
|
15
|
-
|
|
16
|
-
class NoFilesSelected(Exception):
|
|
17
|
-
def __init__(self, folder, message='No file found in folder'):
|
|
18
|
-
self.message = f'{message}: {folder}'
|
|
19
|
-
super().__init__(self.message)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
#TODO da implementare nei metodi. E aggiungere anche i campi MaxMean e MaxStd
|
|
24
|
-
@dataclass
|
|
25
|
-
class Statistics:
|
|
26
|
-
BFSmean: np.array([])
|
|
27
|
-
BFSstd: np.array([])
|
|
28
|
-
BFSstd_mean: float
|
|
29
|
-
|
|
30
|
-
class Profile:
|
|
31
|
-
|
|
32
|
-
filename: str = ''
|
|
33
|
-
plotter: Plotter
|
|
34
|
-
settings: Settings
|
|
35
|
-
sw_version: str = '<1.2.0.0'
|
|
36
|
-
BFS: np.ndarray = np.array([])
|
|
37
|
-
MaxGain: np.ndarray = np.array([])
|
|
38
|
-
timestamp: datetime = datetime.now
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def __init__(self, filename: Union[str,Path], plotter: Plotter = Plotly(), name: str = None) -> None:
|
|
42
|
-
self.filename = filename
|
|
43
|
-
self.plotter = plotter
|
|
44
|
-
with open(self.filename) as file:
|
|
45
|
-
text = load(file)
|
|
46
|
-
self.settings = parseSettingsDict(text['Settings'])
|
|
47
|
-
if 'sw_version' in text:
|
|
48
|
-
self.sw_version = text['sw_version']
|
|
49
|
-
if 'sw_version' in text and text['sw_version'] == '':
|
|
50
|
-
self.sw_version = 'ambiente sviluppo'
|
|
51
|
-
self.timestamp = datetime.strptime(
|
|
52
|
-
text['Time Stamp'], '%Y-%m-%d'+'T'+'%H:%M:%S.%f'+'Z') # "2021-11-08T16:51:16.652Z"
|
|
53
|
-
if not name:
|
|
54
|
-
self.name = self.timestamp.strftime("%m/%d/%Y, %H:%M:%S")
|
|
55
|
-
else:
|
|
56
|
-
self.name = name
|
|
57
|
-
|
|
58
|
-
self.BFS = np.array(text['Profile'])
|
|
59
|
-
self._createPositionArray()
|
|
60
|
-
if 'arrayMaxGain' in text:
|
|
61
|
-
self.MaxGain = np.array(text['arrayMaxGain'])
|
|
62
|
-
|
|
63
|
-
def _createPositionArray(self):
|
|
64
|
-
self.position = np.linspace(
|
|
65
|
-
0, self.settings.Cable.Length, num=len(self.BFS), endpoint=True)
|
|
66
|
-
self.spatialResolution = self.position[1]
|
|
67
|
-
|
|
68
|
-
def plot(self,title:str = None):
|
|
69
|
-
if not title:
|
|
70
|
-
title = self.name
|
|
71
|
-
# TODO usare xrange espresso in metri per affettare array e poi passarli a single_plot. xrange:Tuple[float,float]=None
|
|
72
|
-
return self.plotter.single_plot(self.position,self.BFS,title=title)
|
|
73
|
-
|
|
74
|
-
def plotMax(self,title: str = None):
|
|
75
|
-
if self.MaxGain.size == 0:
|
|
76
|
-
warnings.warn("Max array in not available. If possibile, load the raw file of the same measure.")
|
|
77
|
-
return None
|
|
78
|
-
if not title:
|
|
79
|
-
title = self.name
|
|
80
|
-
return self.plotter.max_plot(self.position, self.MaxGain, title)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
class multipleProfile():
|
|
84
|
-
|
|
85
|
-
statistics: Statistics
|
|
86
|
-
plotter: Plotter
|
|
87
|
-
|
|
88
|
-
def __init__(self, folder: Union[str,Path], plotter: Plotter = Plotly(),
|
|
89
|
-
n_measure: int = None,
|
|
90
|
-
start_measure: Union[int,datetime] = 0,
|
|
91
|
-
stop_measure: datetime = None) -> None:
|
|
92
|
-
|
|
93
|
-
self.folder = folder
|
|
94
|
-
self.plotter = plotter
|
|
95
|
-
|
|
96
|
-
filelist = glob(path.join(folder,'*.json'))
|
|
97
|
-
if start_measure and isinstance(start_measure, datetime):
|
|
98
|
-
timestamps_files = [ datetime.strptime('_'.join(path.basename(file).split('_')[:2]), '%Y-%m-%d_%H-%M-%S.%f' ) for file in filelist]
|
|
99
|
-
primo = next((x for x,value in enumerate(timestamps_files) if value >= start_measure),0)
|
|
100
|
-
if stop_measure:
|
|
101
|
-
ultimo = next((x for x,value in enumerate(timestamps_files) if value > stop_measure),len(filelist))
|
|
102
|
-
elif n_measure:
|
|
103
|
-
ultimo = primo + n_measure
|
|
104
|
-
else:
|
|
105
|
-
ultimo = len(filelist)
|
|
106
|
-
filelist = filelist[primo:ultimo]
|
|
107
|
-
|
|
108
|
-
if n_measure and (start_measure==0 or isinstance(start_measure,int)):
|
|
109
|
-
filelist = filelist[start_measure:start_measure+n_measure]
|
|
110
|
-
|
|
111
|
-
if isinstance(start_measure,int) and not n_measure and stop_measure:
|
|
112
|
-
timestamps_files = [ datetime.strptime('_'.join(path.basename(file).split('_')[:2]), '%Y-%m-%d_%H-%M-%S.%f' ) for file in filelist]
|
|
113
|
-
ultimo = next((x for x,value in enumerate(timestamps_files) if value > stop_measure),len(filelist))
|
|
114
|
-
filelist = filelist[start_measure:ultimo]
|
|
115
|
-
|
|
116
|
-
if len(filelist) == 0:
|
|
117
|
-
raise NoFilesSelected(folder=folder)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
timestamps = list()
|
|
121
|
-
with Bar('Redaing files',max=len(filelist)) as bar:
|
|
122
|
-
for file in filelist:
|
|
123
|
-
temp = Profile(filename=file)
|
|
124
|
-
timestamps.append(temp.timestamp)
|
|
125
|
-
try:
|
|
126
|
-
self.BFS = np.column_stack((self.BFS, temp.BFS))
|
|
127
|
-
self.MaxGain = np.column_stack((self.MaxGain, temp.MaxGain))
|
|
128
|
-
except AttributeError:
|
|
129
|
-
self.BFS = temp.BFS
|
|
130
|
-
self.MaxGain = temp.MaxGain
|
|
131
|
-
bar.next()
|
|
132
|
-
|
|
133
|
-
self.timestamps = np.array(timestamps)
|
|
134
|
-
self.settings = temp.settings
|
|
135
|
-
self.sw_version = temp.sw_version
|
|
136
|
-
self.position = temp.position
|
|
137
|
-
self.calcStatistics()
|
|
138
|
-
self.MaxGainMean = self.MaxGain.mean(axis=1)
|
|
139
|
-
self.MaxGainStd = self.MaxGain.std(axis=1)
|
|
140
|
-
|
|
141
|
-
def calcCorrelations(self, type:Literal['max','bfs'],
|
|
142
|
-
reference:Literal['first','previous']='previous',
|
|
143
|
-
range:Tuple[float,float]=None) -> np.array:
|
|
144
|
-
'''Ritorna correlazione tra prima misura e misura n-esima.
|
|
145
|
-
Si può scegliere se effettuarla su matrice dei BFS o matrice dei massimi'''
|
|
146
|
-
|
|
147
|
-
if type == 'max':
|
|
148
|
-
correlations = np.corrcoef(self.MaxGain[range[0]:range[1]] if range else self.MaxGain,rowvar=False)
|
|
149
|
-
else:
|
|
150
|
-
correlations = np.corrcoef(self.BFS[range[0]:range[1]] if range else self.BFS,rowvar=False)
|
|
151
|
-
|
|
152
|
-
if reference == 'first':
|
|
153
|
-
return correlations[0,:]
|
|
154
|
-
|
|
155
|
-
indici = np.arange(1,np.shape(correlations)[0])
|
|
156
|
-
return np.insert(correlations[indici,indici-1],0,1)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
def calcStatistics(self, plot:bool=False, range:Tuple[float,float]=None, title:str=None)->Statistics:
|
|
160
|
-
# TODO gestione input range
|
|
161
|
-
self.statistics = Statistics(BFSmean=self.BFS.mean(axis=1),
|
|
162
|
-
BFSstd=self.BFS.std(axis=1),
|
|
163
|
-
BFSstd_mean=self.BFS.std(axis=1).mean())
|
|
164
|
-
|
|
165
|
-
if plot:
|
|
166
|
-
if not title:
|
|
167
|
-
title=self.folder
|
|
168
|
-
return self.plotter.statistics(self.position,
|
|
169
|
-
self.statistics.BFSmean,
|
|
170
|
-
self.statistics.BFSstd, title=title)
|
|
171
|
-
return self.statistics
|
|
172
|
-
|
|
173
|
-
def plotStatistics(self, title:str=None):
|
|
174
|
-
if not title:
|
|
175
|
-
title=self.folder
|
|
176
|
-
# TODO se sono state calcolate con range allora position è sbagliato
|
|
177
|
-
return self.plotter.statistics(self.position, self.statistics, title=title)
|
|
178
|
-
|
|
179
|
-
def plot(self, startTime: datetime = datetime.min, stopTime: datetime = datetime.now(), title: str = None):
|
|
180
|
-
if not title:
|
|
181
|
-
title=self.folder
|
|
182
|
-
match = [i for i,date in enumerate(self.timestamps) if date >= startTime and date <= stopTime]
|
|
183
|
-
return self.plotter.multiple_plot(self.position,self.BFS[:,match],self.timestamps[match],title=title)
|
|
184
|
-
|
|
185
|
-
def plotMax(self,title: str = None):
|
|
186
|
-
if self.MaxGain.size == 0:
|
|
187
|
-
warnings.warn("Max array in not available. If possibile, load the raw file of the same measure.")
|
|
188
|
-
return None
|
|
189
|
-
if not title:
|
|
190
|
-
title = self.folder
|
|
191
|
-
return self.plotter.max_stat_plot(self.MaxGainMean, self.MaxGainStd, title)
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
class Raw():
|
|
195
|
-
|
|
196
|
-
filename: Union[str,Path] = Path('')
|
|
197
|
-
plotter: Plotter
|
|
198
|
-
settings: Settings
|
|
199
|
-
sw_version: str = '<1.2.0.0'
|
|
200
|
-
BGS: np.ndarray = np.array([])
|
|
201
|
-
residuo: np.ndarray = np.array([])
|
|
202
|
-
timestamp: datetime = datetime.now
|
|
203
|
-
|
|
204
|
-
def __init__(self, filename: Union[str,Path], plotter: Plotter = Plotly()) -> None:
|
|
205
|
-
self.filename = filename
|
|
206
|
-
self.plotter = plotter
|
|
207
|
-
with open(self.filename) as file:
|
|
208
|
-
text = load(file)
|
|
209
|
-
self.settings = parseSettingsDict(text['Settings'])
|
|
210
|
-
if 'sw_version' in text:
|
|
211
|
-
self.sw_version = text['sw_version']
|
|
212
|
-
if 'sw_version' in text and text['sw_version'] == '':
|
|
213
|
-
self.sw_version = 'ambiente sviluppo'
|
|
214
|
-
self.BGS = np.transpose(np.array(text['Raw']))
|
|
215
|
-
self.timestamp = datetime.strptime(
|
|
216
|
-
text['Time Stamp'], '%Y-%m-%d'+'T'+'%H:%M:%S.%f'+'Z') # "2021-11-08T16:51:16.652Z"
|
|
217
|
-
self._createPositionArray()
|
|
218
|
-
self._createFrequencyArray()
|
|
219
|
-
try:
|
|
220
|
-
self.residuo = np.array(text['residuo'])
|
|
221
|
-
except KeyError:
|
|
222
|
-
self.residuo = np.zeros(np.shape(self.frequency))
|
|
223
|
-
|
|
224
|
-
def _createPositionArray(self) -> None:
|
|
225
|
-
'''Crea array numpy delle posizioni e la risoluzione spaziale'''
|
|
226
|
-
self.position = np.linspace(
|
|
227
|
-
0, self.settings.Cable.Length, num=self.BGS.shape[1], endpoint=True)
|
|
228
|
-
self.spatialResolution = self.position[1]
|
|
229
|
-
|
|
230
|
-
def _createFrequencyArray(self) -> None:
|
|
231
|
-
'''Crea array numpy delle frequenze, espresse in GHz'''
|
|
232
|
-
self.frequency = np.linspace( self.settings.Clock.StartMHz,
|
|
233
|
-
self.settings.Clock.StartMHz + self.settings.Clock.StepMHz * self.BGS.shape[0], num= self.BGS.shape[0], endpoint=True) / 1000
|
|
234
|
-
|
|
235
|
-
def plot2d(self, title: str = None):
|
|
236
|
-
if not title:
|
|
237
|
-
title=self.filename
|
|
238
|
-
return self.plotter.raw2d_plot(self.position, self.frequency, self.BGS, title=title)
|
|
239
|
-
|
|
240
|
-
def plot3d(self, title: str = None):
|
|
241
|
-
if not title:
|
|
242
|
-
title=self.filename
|
|
243
|
-
return self.plotter.raw3d_plot(self.position, self.frequency, self.BGS, title=title)
|
|
244
|
-
|
|
245
|
-
def plotBGS(self, index: int = None, title: str = None):
|
|
246
|
-
'''Plot 2D di tutti gli spettri BGS'''
|
|
247
|
-
if not title:
|
|
248
|
-
title=self.filename
|
|
249
|
-
return self.plotter.rawBGS_plot(self.frequency, self.BGS, index=index, title=title)
|
|
250
|
-
|
|
251
|
-
def plotMax(self, title: str = None):
|
|
252
|
-
if not title:
|
|
253
|
-
title=self.filename
|
|
254
|
-
return self.plotter.max_plot(self.position, self.BGS.max(axis=0), title)
|
|
255
|
-
|
|
256
|
-
if __name__ == '__main__':
|
|
257
|
-
'''Non va se si lancia direttamente questo script a meno di non cambiare i primi due import da modules.settings a settings; uguale per plotter.'''
|
|
258
|
-
#a = Profile(filename='data/profiles/2021-11-08_16-51-16.652_rawarray.json')
|
|
259
|
-
#b = multipleProfile(folder='data/profiles/')
|
|
260
|
-
c = Raw(filename='data/raw/2021-11-08_16-51-16.652_rawmatrix.json')
|
|
261
|
-
# print(b.BFS.shape)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|