shepherd-data 2023.2.1__py3-none-any.whl → 2023.3.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.
- shepherd_data/__init__.py +2 -1
- shepherd_data/calibration.py +17 -9
- shepherd_data/cli.py +24 -12
- shepherd_data/ivonne.py +35 -24
- shepherd_data/mppt.py +12 -7
- shepherd_data/reader.py +118 -77
- shepherd_data/writer.py +111 -95
- {shepherd_data-2023.2.1.dist-info → shepherd_data-2023.3.1.dist-info}/METADATA +40 -30
- shepherd_data-2023.3.1.dist-info/RECORD +14 -0
- {shepherd_data-2023.2.1.dist-info → shepherd_data-2023.3.1.dist-info}/WHEEL +1 -1
- shepherd_data-2023.2.1.dist-info/RECORD +0 -14
- {shepherd_data-2023.2.1.dist-info → shepherd_data-2023.3.1.dist-info}/LICENSE +0 -0
- {shepherd_data-2023.2.1.dist-info → shepherd_data-2023.3.1.dist-info}/entry_points.txt +0 -0
- {shepherd_data-2023.2.1.dist-info → shepherd_data-2023.3.1.dist-info}/top_level.txt +0 -0
- {shepherd_data-2023.2.1.dist-info → shepherd_data-2023.3.1.dist-info}/zip-safe +0 -0
shepherd_data/writer.py
CHANGED
|
@@ -5,7 +5,6 @@ import logging
|
|
|
5
5
|
import math
|
|
6
6
|
from itertools import product
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import NoReturn
|
|
9
8
|
from typing import Optional
|
|
10
9
|
from typing import Union
|
|
11
10
|
|
|
@@ -27,7 +26,7 @@ def unique_path(base_path: Union[str, Path], suffix: str) -> Path:
|
|
|
27
26
|
"""
|
|
28
27
|
counter = 0
|
|
29
28
|
while True:
|
|
30
|
-
path = base_path.with_suffix(f".{counter}{suffix}")
|
|
29
|
+
path = Path(base_path).with_suffix(f".{counter}{suffix}")
|
|
31
30
|
if not path.exists():
|
|
32
31
|
return path
|
|
33
32
|
counter += 1
|
|
@@ -57,35 +56,32 @@ class Writer(Reader):
|
|
|
57
56
|
# -> lower levels seem fine
|
|
58
57
|
# -> _algo=number instead of "gzip" is read as compression level for gzip
|
|
59
58
|
# -> comparison / benchmarks https://www.h5py.org/lzf/
|
|
60
|
-
comp_default = 1
|
|
59
|
+
comp_default: int = 1
|
|
61
60
|
mode_default: str = "harvester"
|
|
62
61
|
datatype_default: str = "ivsample"
|
|
63
62
|
|
|
64
63
|
_chunk_shape: tuple = (Reader.samples_per_buffer,)
|
|
65
64
|
|
|
66
|
-
_logger: logging.Logger = logging.getLogger("SHPData.Writer")
|
|
67
|
-
|
|
68
65
|
def __init__(
|
|
69
66
|
self,
|
|
70
67
|
file_path: Path,
|
|
71
|
-
mode: str = None,
|
|
72
|
-
datatype: str = None,
|
|
73
|
-
window_samples: int = None,
|
|
74
|
-
cal_data: dict = None,
|
|
68
|
+
mode: Optional[str] = None,
|
|
69
|
+
datatype: Optional[str] = None,
|
|
70
|
+
window_samples: Optional[int] = None,
|
|
71
|
+
cal_data: Optional[dict] = None,
|
|
75
72
|
modify_existing: bool = False,
|
|
76
73
|
compression: Union[None, str, int] = "default",
|
|
77
74
|
verbose: Optional[bool] = True,
|
|
78
75
|
):
|
|
79
|
-
super().__init__(file_path=None, verbose=verbose)
|
|
80
|
-
|
|
81
76
|
file_path = Path(file_path)
|
|
82
77
|
self._modify = modify_existing
|
|
83
78
|
|
|
84
|
-
if
|
|
85
|
-
self._logger
|
|
79
|
+
if not hasattr(self, "_logger"):
|
|
80
|
+
self._logger: logging.Logger = logging.getLogger("SHPData.Writer")
|
|
81
|
+
# -> logger gets configured in reader()
|
|
86
82
|
|
|
87
83
|
if self._modify or not file_path.exists():
|
|
88
|
-
self._file_path = file_path
|
|
84
|
+
self._file_path: Path = file_path
|
|
89
85
|
self._logger.info("Storing data to '%s'", self._file_path)
|
|
90
86
|
else:
|
|
91
87
|
base_dir = file_path.resolve().parents[0]
|
|
@@ -97,94 +93,60 @@ class Writer(Reader):
|
|
|
97
93
|
)
|
|
98
94
|
|
|
99
95
|
if not isinstance(mode, (str, type(None))):
|
|
100
|
-
raise TypeError(f"
|
|
96
|
+
raise TypeError(f"Can't handle type '{type(mode)}' for mode [str, None]")
|
|
101
97
|
if isinstance(mode, str) and mode not in self.mode_dtype_dict:
|
|
102
|
-
raise ValueError(
|
|
98
|
+
raise ValueError(
|
|
99
|
+
f"Can't handle mode '{mode}' " f"(choose one of {self.mode_dtype_dict})"
|
|
100
|
+
)
|
|
101
|
+
if not isinstance(window_samples, (int, type(None))):
|
|
102
|
+
raise TypeError(
|
|
103
|
+
f"Can't handle type '{type(window_samples)}' for window_samples [int, None]"
|
|
104
|
+
)
|
|
105
|
+
if not isinstance(cal_data, (dict, type(None))):
|
|
106
|
+
raise TypeError(
|
|
107
|
+
f"Can't handle type '{type(cal_data)}' for cal_data [dict, None]"
|
|
108
|
+
)
|
|
103
109
|
|
|
104
110
|
if not isinstance(datatype, (str, type(None))):
|
|
105
|
-
raise TypeError(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
):
|
|
111
|
-
raise ValueError(
|
|
111
|
+
raise TypeError(
|
|
112
|
+
f"Can't handle type '{type(datatype)}' for datatype [str, None]"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
_dtypes = self.mode_dtype_dict[self.mode_default if (mode is None) else mode]
|
|
116
|
+
if isinstance(datatype, str) and datatype not in _dtypes:
|
|
117
|
+
raise ValueError(
|
|
118
|
+
f"Can't handle value '{datatype}' of datatype "
|
|
119
|
+
f"(choose one of {_dtypes})"
|
|
120
|
+
)
|
|
112
121
|
|
|
113
122
|
if self._modify:
|
|
114
123
|
self._mode = mode
|
|
115
|
-
self._cal =
|
|
124
|
+
self._cal = (
|
|
125
|
+
cal_data if isinstance(cal_data, dict) else cal_default
|
|
126
|
+
) # TODO: switch to pydantic
|
|
116
127
|
self._datatype = datatype
|
|
117
128
|
self._window_samples = window_samples
|
|
118
129
|
else:
|
|
119
|
-
self._mode =
|
|
120
|
-
self._cal =
|
|
121
|
-
self._datatype =
|
|
122
|
-
|
|
130
|
+
self._mode = mode if isinstance(mode, str) else self.mode_default
|
|
131
|
+
self._cal = cal_data if isinstance(cal_data, dict) else cal_default
|
|
132
|
+
self._datatype = (
|
|
133
|
+
datatype if isinstance(datatype, str) else self.datatype_default
|
|
134
|
+
)
|
|
135
|
+
self._window_samples = (
|
|
136
|
+
window_samples if isinstance(window_samples, int) else 0
|
|
137
|
+
)
|
|
123
138
|
|
|
124
139
|
if compression in [None, "lzf", 1]: # order of recommendation
|
|
125
140
|
self._compression_algo = compression
|
|
126
141
|
else:
|
|
127
142
|
self._compression_algo = self.comp_default
|
|
128
143
|
|
|
129
|
-
|
|
130
|
-
"""Initializes the structure of the HDF5 file
|
|
131
|
-
|
|
132
|
-
HDF5 is hierarchically structured and before writing data, we have to
|
|
133
|
-
setup this structure, i.e. creating the right groups with corresponding
|
|
134
|
-
data types. We will store 3 types of data in a database: The
|
|
135
|
-
actual IV samples recorded either from the harvester (during recording)
|
|
136
|
-
or the target (during emulation). Any log messages, that can be used to
|
|
137
|
-
store relevant events or tag some parts of the recorded data.
|
|
138
|
-
|
|
139
|
-
"""
|
|
144
|
+
# open file
|
|
140
145
|
if self._modify:
|
|
141
|
-
self.h5file = h5py.File(self._file_path, "r+")
|
|
146
|
+
self.h5file = h5py.File(self._file_path, "r+") # = rw
|
|
142
147
|
else:
|
|
143
|
-
self.h5file = h5py.File(self._file_path, "w")
|
|
144
|
-
|
|
145
|
-
# Store voltage and current samples in the data group,
|
|
146
|
-
# both are stored as 4 Byte unsigned int
|
|
147
|
-
gp_data = self.h5file.create_group("data")
|
|
148
|
-
# the size of window_samples-attribute in harvest-data indicates ivcurves as input
|
|
149
|
-
# -> emulator uses virtual-harvester, field will be adjusted by .embed_config()
|
|
150
|
-
gp_data.attrs["window_samples"] = 0
|
|
151
|
-
|
|
152
|
-
gp_data.create_dataset(
|
|
153
|
-
"time",
|
|
154
|
-
(0,),
|
|
155
|
-
dtype="u8",
|
|
156
|
-
maxshape=(None,),
|
|
157
|
-
chunks=self._chunk_shape,
|
|
158
|
-
compression=self._compression_algo,
|
|
159
|
-
)
|
|
160
|
-
gp_data["time"].attrs["unit"] = "ns"
|
|
161
|
-
gp_data["time"].attrs["description"] = "system time [ns]"
|
|
162
|
-
|
|
163
|
-
gp_data.create_dataset(
|
|
164
|
-
"current",
|
|
165
|
-
(0,),
|
|
166
|
-
dtype="u4",
|
|
167
|
-
maxshape=(None,),
|
|
168
|
-
chunks=self._chunk_shape,
|
|
169
|
-
compression=self._compression_algo,
|
|
170
|
-
)
|
|
171
|
-
gp_data["current"].attrs["unit"] = "A"
|
|
172
|
-
gp_data["current"].attrs[
|
|
173
|
-
"description"
|
|
174
|
-
] = "current [A] = value * gain + offset"
|
|
175
|
-
|
|
176
|
-
gp_data.create_dataset(
|
|
177
|
-
"voltage",
|
|
178
|
-
(0,),
|
|
179
|
-
dtype="u4",
|
|
180
|
-
maxshape=(None,),
|
|
181
|
-
chunks=self._chunk_shape,
|
|
182
|
-
compression=self._compression_algo,
|
|
183
|
-
)
|
|
184
|
-
gp_data["voltage"].attrs["unit"] = "V"
|
|
185
|
-
gp_data["voltage"].attrs[
|
|
186
|
-
"description"
|
|
187
|
-
] = "voltage [V] = value * gain + offset"
|
|
148
|
+
self.h5file = h5py.File(self._file_path, "w") # write, truncate if exist
|
|
149
|
+
self._create_skeleton()
|
|
188
150
|
|
|
189
151
|
# Store the mode in order to allow user to differentiate harvesting vs emulation data
|
|
190
152
|
if isinstance(self._mode, str) and self._mode in self.mode_dtype_dict:
|
|
@@ -208,11 +170,13 @@ class Writer(Reader):
|
|
|
208
170
|
self.h5file["data"][channel].attrs[parameter] = self._cal[channel][
|
|
209
171
|
parameter
|
|
210
172
|
]
|
|
173
|
+
super().__init__(file_path=None, verbose=verbose)
|
|
211
174
|
|
|
175
|
+
def __enter__(self):
|
|
212
176
|
super().__enter__()
|
|
213
177
|
return self
|
|
214
178
|
|
|
215
|
-
def __exit__(self, *exc):
|
|
179
|
+
def __exit__(self, *exc): # type: ignore
|
|
216
180
|
self._align()
|
|
217
181
|
self._refresh_file_stats()
|
|
218
182
|
self._logger.info(
|
|
@@ -224,12 +188,63 @@ class Writer(Reader):
|
|
|
224
188
|
self.is_valid()
|
|
225
189
|
self.h5file.close()
|
|
226
190
|
|
|
191
|
+
def _create_skeleton(self) -> None:
|
|
192
|
+
"""Initializes the structure of the HDF5 file
|
|
193
|
+
|
|
194
|
+
HDF5 is hierarchically structured and before writing data, we have to
|
|
195
|
+
setup this structure, i.e. creating the right groups with corresponding
|
|
196
|
+
data types. We will store 3 types of data in a database: The
|
|
197
|
+
actual IV samples recorded either from the harvester (during recording)
|
|
198
|
+
or the target (during emulation). Any log messages, that can be used to
|
|
199
|
+
store relevant events or tag some parts of the recorded data.
|
|
200
|
+
|
|
201
|
+
"""
|
|
202
|
+
# Store voltage and current samples in the data group,
|
|
203
|
+
# both are stored as 4 Byte unsigned int
|
|
204
|
+
gp_data = self.h5file.create_group("data")
|
|
205
|
+
# the size of window_samples-attribute in harvest-data indicates ivcurves as input
|
|
206
|
+
# -> emulator uses virtual-harvester, field will be adjusted by .embed_config()
|
|
207
|
+
gp_data.attrs["window_samples"] = 0
|
|
208
|
+
|
|
209
|
+
gp_data.create_dataset(
|
|
210
|
+
"time",
|
|
211
|
+
(0,),
|
|
212
|
+
dtype="u8",
|
|
213
|
+
maxshape=(None,),
|
|
214
|
+
chunks=self._chunk_shape,
|
|
215
|
+
compression=self._compression_algo,
|
|
216
|
+
)
|
|
217
|
+
gp_data["time"].attrs["unit"] = "ns"
|
|
218
|
+
gp_data["time"].attrs["description"] = "system time [ns]"
|
|
219
|
+
|
|
220
|
+
gp_data.create_dataset(
|
|
221
|
+
"current",
|
|
222
|
+
(0,),
|
|
223
|
+
dtype="u4",
|
|
224
|
+
maxshape=(None,),
|
|
225
|
+
chunks=self._chunk_shape,
|
|
226
|
+
compression=self._compression_algo,
|
|
227
|
+
)
|
|
228
|
+
gp_data["current"].attrs["unit"] = "A"
|
|
229
|
+
gp_data["current"].attrs["description"] = "current [A] = value * gain + offset"
|
|
230
|
+
|
|
231
|
+
gp_data.create_dataset(
|
|
232
|
+
"voltage",
|
|
233
|
+
(0,),
|
|
234
|
+
dtype="u4",
|
|
235
|
+
maxshape=(None,),
|
|
236
|
+
chunks=self._chunk_shape,
|
|
237
|
+
compression=self._compression_algo,
|
|
238
|
+
)
|
|
239
|
+
gp_data["voltage"].attrs["unit"] = "V"
|
|
240
|
+
gp_data["voltage"].attrs["description"] = "voltage [V] = value * gain + offset"
|
|
241
|
+
|
|
227
242
|
def append_iv_data_raw(
|
|
228
243
|
self,
|
|
229
244
|
timestamp_ns: Union[np.ndarray, float, int],
|
|
230
245
|
voltage: np.ndarray,
|
|
231
246
|
current: np.ndarray,
|
|
232
|
-
) ->
|
|
247
|
+
) -> None:
|
|
233
248
|
"""Writes raw data to database
|
|
234
249
|
|
|
235
250
|
Args:
|
|
@@ -266,23 +281,24 @@ class Writer(Reader):
|
|
|
266
281
|
self,
|
|
267
282
|
timestamp: Union[np.ndarray, float],
|
|
268
283
|
voltage: np.ndarray,
|
|
269
|
-
current: np.
|
|
270
|
-
) ->
|
|
284
|
+
current: np.ndarray,
|
|
285
|
+
) -> None:
|
|
271
286
|
"""Writes data (in SI / physical unit) to file, but converts it to raw-data first
|
|
272
287
|
|
|
288
|
+
SI-value [SI-Unit] = raw-value * gain + offset,
|
|
289
|
+
|
|
273
290
|
Args:
|
|
274
291
|
timestamp: python timestamp (time.time()) in seconds (si-unit)
|
|
275
292
|
-> provide start of buffer or whole ndarray
|
|
276
293
|
voltage: ndarray in physical-unit V
|
|
277
294
|
current: ndarray in physical-unit A
|
|
278
295
|
"""
|
|
279
|
-
# SI-value [SI-Unit] = raw-value * gain + offset,
|
|
280
296
|
timestamp = timestamp * 10**9
|
|
281
297
|
voltage = si_to_raw(voltage, self._cal["voltage"])
|
|
282
298
|
current = si_to_raw(current, self._cal["current"])
|
|
283
299
|
self.append_iv_data_raw(timestamp, voltage, current)
|
|
284
300
|
|
|
285
|
-
def _align(self) ->
|
|
301
|
+
def _align(self) -> None:
|
|
286
302
|
"""Align datasets with buffer-size of shepherd"""
|
|
287
303
|
self._refresh_file_stats()
|
|
288
304
|
n_buff = self.ds_time.size / self.samples_per_buffer
|
|
@@ -299,11 +315,11 @@ class Writer(Reader):
|
|
|
299
315
|
self.ds_voltage.resize((size_new,))
|
|
300
316
|
self.ds_current.resize((size_new,))
|
|
301
317
|
|
|
302
|
-
def __setitem__(self, key, item):
|
|
318
|
+
def __setitem__(self, key: str, item): # type: ignore
|
|
303
319
|
"""A convenient interface to store relevant key-value data (attribute) if H5-structure"""
|
|
304
320
|
return self.h5file.attrs.__setitem__(key, item)
|
|
305
321
|
|
|
306
|
-
def set_config(self, data: dict) ->
|
|
322
|
+
def set_config(self, data: dict) -> None:
|
|
307
323
|
"""Important Step to get a self-describing Output-File
|
|
308
324
|
|
|
309
325
|
:param data: from virtual harvester or converter / source
|
|
@@ -314,14 +330,14 @@ class Writer(Reader):
|
|
|
314
330
|
if "window_samples" in data:
|
|
315
331
|
self.set_window_samples(data["window_samples"])
|
|
316
332
|
|
|
317
|
-
def set_window_samples(self, samples: int = 0) ->
|
|
333
|
+
def set_window_samples(self, samples: int = 0) -> None:
|
|
318
334
|
"""parameter essential for ivcurves
|
|
319
335
|
|
|
320
336
|
:param samples: length of window / voltage sweep
|
|
321
337
|
"""
|
|
322
338
|
self.h5file["data"].attrs["window_samples"] = samples
|
|
323
339
|
|
|
324
|
-
def set_hostname(self, name: str) ->
|
|
340
|
+
def set_hostname(self, name: str) -> None:
|
|
325
341
|
"""option to distinguish the host, target or data-source in the testbed
|
|
326
342
|
-> perfect for plotting later
|
|
327
343
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: shepherd-data
|
|
3
|
-
Version: 2023.
|
|
3
|
+
Version: 2023.3.1
|
|
4
4
|
Summary: Programming- and CLI-Interface for the h5-dataformat of the Shepherd-Testbed
|
|
5
5
|
Home-page: https://pypi.org/project/shepherd-data/
|
|
6
6
|
Author: Ingmar Splitt, Kai Geissdoerfer
|
|
@@ -45,43 +45,53 @@ Requires-Dist: pylint ; extra == 'dev'
|
|
|
45
45
|
Requires-Dist: flake8 ; extra == 'dev'
|
|
46
46
|
Requires-Dist: twine ; extra == 'dev'
|
|
47
47
|
Requires-Dist: pre-commit ; extra == 'dev'
|
|
48
|
+
Requires-Dist: pyright ; extra == 'dev'
|
|
49
|
+
Requires-Dist: pandas-stubs ; extra == 'dev'
|
|
48
50
|
Provides-Extra: test
|
|
49
51
|
Requires-Dist: pytest ; extra == 'test'
|
|
50
52
|
Requires-Dist: pytest-click ; extra == 'test'
|
|
51
53
|
Requires-Dist: coverage ; extra == 'test'
|
|
52
54
|
|
|
55
|
+
# Shepherd - Data
|
|
56
|
+
|
|
53
57
|
[](https://pypi.org/project/shepherd_data)
|
|
54
58
|
[](https://github.com/orgua/shepherd-datalib/actions/workflows/python-app.yml)
|
|
55
59
|
[](https://github.com/psf/black)
|
|
56
60
|
|
|
57
|
-
## Shepherd - Data
|
|
58
|
-
|
|
59
61
|
This Python Module eases the handling of hdf5-recordings used by the [shepherd](https://github.com/orgua/shepherd)-testbed. Users can read, validate and create files and also extract, down-sample and plot information.
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
---
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
**Main Project**: [https://github.com/orgua/shepherd](https://github.com/orgua/shepherd)
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
**Source Code**: [https://github.com/orgua/shepherd-datalib](https://github.com/orgua/shepherd-datalib)
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Installation
|
|
72
|
+
|
|
73
|
+
### PIP - Online
|
|
74
|
+
|
|
75
|
+
```shell
|
|
66
76
|
pip3 install shepherd-data
|
|
67
77
|
```
|
|
68
78
|
|
|
69
|
-
|
|
79
|
+
### PIP - Offline
|
|
70
80
|
|
|
71
81
|
- clone repository
|
|
72
82
|
- navigate shell into directory
|
|
73
83
|
- install local module
|
|
74
84
|
|
|
75
|
-
```
|
|
85
|
+
```shell
|
|
76
86
|
git clone https://github.com/orgua/shepherd-datalib
|
|
77
87
|
cd .\shepherd-datalib
|
|
78
88
|
|
|
79
89
|
pip3 install ./
|
|
80
90
|
```
|
|
81
91
|
|
|
82
|
-
|
|
92
|
+
## Development
|
|
83
93
|
|
|
84
|
-
|
|
94
|
+
### PipEnv
|
|
85
95
|
|
|
86
96
|
- clone repository
|
|
87
97
|
- navigate shell into directory
|
|
@@ -103,20 +113,20 @@ pipenv update
|
|
|
103
113
|
pipenv install --dev pytest
|
|
104
114
|
```
|
|
105
115
|
|
|
106
|
-
|
|
116
|
+
### running Testbench
|
|
107
117
|
|
|
108
118
|
- run pytest
|
|
109
119
|
|
|
110
|
-
```
|
|
120
|
+
```shell
|
|
111
121
|
pytest
|
|
112
122
|
```
|
|
113
123
|
|
|
114
|
-
|
|
124
|
+
### code coverage (with pytest)
|
|
115
125
|
|
|
116
126
|
- run coverage
|
|
117
127
|
- check results (in browser `./htmlcov/index.html`)
|
|
118
128
|
|
|
119
|
-
```
|
|
129
|
+
```shell
|
|
120
130
|
coverage run -m pytest
|
|
121
131
|
|
|
122
132
|
coverage html
|
|
@@ -124,11 +134,11 @@ coverage html
|
|
|
124
134
|
coverage report
|
|
125
135
|
```
|
|
126
136
|
|
|
127
|
-
|
|
137
|
+
## Programming Interface
|
|
128
138
|
|
|
129
|
-
|
|
139
|
+
### Basic Usage (recommendation)
|
|
130
140
|
|
|
131
|
-
```
|
|
141
|
+
```python
|
|
132
142
|
import shepherd_data as shpd
|
|
133
143
|
|
|
134
144
|
with shpd.Reader("./hrv_sawtooth_1h.h5") as db:
|
|
@@ -137,7 +147,7 @@ with shpd.Reader("./hrv_sawtooth_1h.h5") as db:
|
|
|
137
147
|
print(f"Config: {db.get_config()}")
|
|
138
148
|
```
|
|
139
149
|
|
|
140
|
-
|
|
150
|
+
### Available Functionality
|
|
141
151
|
|
|
142
152
|
- `Reader()`
|
|
143
153
|
- file can be checked for plausibility and validity (`is_valid()`)
|
|
@@ -172,7 +182,7 @@ with shpd.Reader("./hrv_sawtooth_1h.h5") as db:
|
|
|
172
182
|
- 50 Hz measurement with Short-Circuit-Current and two other parameters
|
|
173
183
|
- recorded with "IVonne"
|
|
174
184
|
|
|
175
|
-
|
|
185
|
+
## CLI-Interface
|
|
176
186
|
|
|
177
187
|
After installing the module the datalib offers some often needed functionality on the command line:
|
|
178
188
|
|
|
@@ -180,7 +190,7 @@ After installing the module the datalib offers some often needed functionality o
|
|
|
180
190
|
|
|
181
191
|
- takes a file or directory as an argument
|
|
182
192
|
|
|
183
|
-
```
|
|
193
|
+
```shell
|
|
184
194
|
shepherd-data validate dir_or_file
|
|
185
195
|
|
|
186
196
|
# examples:
|
|
@@ -193,7 +203,7 @@ shepherd-data validate hrv_saw_1h.h5
|
|
|
193
203
|
- takes a file or directory as an argument
|
|
194
204
|
- can take down-sample-factor as an argument
|
|
195
205
|
|
|
196
|
-
```
|
|
206
|
+
```shell
|
|
197
207
|
shepherd-data extract [-f ds-factor] [-s separator_symbol] dir_or_file
|
|
198
208
|
|
|
199
209
|
# examples:
|
|
@@ -205,7 +215,7 @@ shepherd-data extract -f 1000 -s ; hrv_saw_1h.h5
|
|
|
205
215
|
|
|
206
216
|
- takes a file or directory as an argument
|
|
207
217
|
|
|
208
|
-
```
|
|
218
|
+
```shell
|
|
209
219
|
shepherd-data extract-meta dir_or_file
|
|
210
220
|
|
|
211
221
|
# examples:
|
|
@@ -219,7 +229,7 @@ shepherd-data extract-meta hrv_saw_1h.h5
|
|
|
219
229
|
- can take start- and end-time as an argument
|
|
220
230
|
- can take image-width and -height as an argument
|
|
221
231
|
|
|
222
|
-
```
|
|
232
|
+
```shell
|
|
223
233
|
shepherd-data plot [-s start_time] [-e end_time] [-w plot_width] [-h plot_height] [--multiplot] dir_or_file
|
|
224
234
|
|
|
225
235
|
# examples:
|
|
@@ -233,7 +243,7 @@ shepherd-data plot -s10 -e20 hrv_saw_1h.h5
|
|
|
233
243
|
- takes a file or directory as an argument
|
|
234
244
|
- can take down-sample-factor as an argument
|
|
235
245
|
|
|
236
|
-
```
|
|
246
|
+
```shell
|
|
237
247
|
shepherd-data downsample [-f ds-factor] [-r sample-rate] dir_or_file
|
|
238
248
|
|
|
239
249
|
# examples:
|
|
@@ -242,7 +252,7 @@ shepherd-data downsample -f 1000 hrv_saw_1h.h5
|
|
|
242
252
|
shepherd-data downsample -r 100 hrv_saw_1h.h5
|
|
243
253
|
```
|
|
244
254
|
|
|
245
|
-
|
|
255
|
+
## Data-Layout and Design choices
|
|
246
256
|
|
|
247
257
|
Details about the file-structure can be found in the [main-project](https://github.com/orgua/shepherd/blob/main/docs/user/data_format.rst).
|
|
248
258
|
|
|
@@ -250,7 +260,7 @@ TODO:
|
|
|
250
260
|
- update design of file
|
|
251
261
|
- data dtype, mode, ...
|
|
252
262
|
|
|
253
|
-
|
|
263
|
+
### Modes and Datatypes
|
|
254
264
|
|
|
255
265
|
- Mode `harvester` recorded a harvesting-source like solar with one of various algorithms
|
|
256
266
|
- Datatype `ivsample` is directly usable by shepherd, input for virtual source / converter
|
|
@@ -259,7 +269,7 @@ TODO:
|
|
|
259
269
|
- Mode `emulator` replayed a harvester-recording through a virtual converter and supplied a target while recording the power-consumption
|
|
260
270
|
- Datatype `ivsample` is the only output of this mode
|
|
261
271
|
|
|
262
|
-
|
|
272
|
+
### Compression & Beaglebone
|
|
263
273
|
|
|
264
274
|
- supported are uncompressed, lzf and gzip with level 1 (order of recommendation)
|
|
265
275
|
- lzf seems better-suited due to lower load, or if space isn't a constraint: uncompressed (None as argument)
|
|
@@ -284,7 +294,7 @@ TODO:
|
|
|
284
294
|
emu_120s_unc_to_unc.h5 -> emulator, cpu_util [%] = 51.69, data-rate = 1564.0 KiB/s
|
|
285
295
|
```
|
|
286
296
|
|
|
287
|
-
|
|
297
|
+
## Release-Procedure
|
|
288
298
|
|
|
289
299
|
- increase version number in __init__.py
|
|
290
300
|
- install and run pre-commit, for QA-Checks, see steps below
|
|
@@ -292,13 +302,13 @@ TODO:
|
|
|
292
302
|
- put together a release on Github - the tag should match current version-number
|
|
293
303
|
- Github automatically pushes release to pypi
|
|
294
304
|
|
|
295
|
-
```
|
|
305
|
+
```shell
|
|
296
306
|
pip3 install pre-commit
|
|
297
307
|
|
|
298
308
|
pre-commit run --all-files
|
|
299
309
|
```
|
|
300
310
|
|
|
301
|
-
|
|
311
|
+
## Open Tasks
|
|
302
312
|
|
|
303
313
|
- [click progressbar](https://click.palletsprojects.com/en/8.1.x/api/#click.progressbar) -> could replace tqdm
|
|
304
314
|
- implementations for this lib
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
shepherd_data/__init__.py,sha256=PcRoZstviwMJ9lX_yD3x7M2xwyuSNgDh-Iz7zc7rfeI,338
|
|
2
|
+
shepherd_data/calibration.py,sha256=QJBioq1VTKEQRxH-kfILZtZj8eQIsg3fuv3Iwo2rDp8,1702
|
|
3
|
+
shepherd_data/cli.py,sha256=nVtSRTdBkCQQSLti2OWF-LhvK1EEh5k_Z7rf4HeRgyY,10785
|
|
4
|
+
shepherd_data/ivonne.py,sha256=eYKa3rxRFbD8b_Svt7vuOEVHQc6V9Facs5DDeK2IgGA,11683
|
|
5
|
+
shepherd_data/mppt.py,sha256=t-GkSmcB8bUaLsqjWsD--voUdFxnNBHIy8D8LcaIXt8,3598
|
|
6
|
+
shepherd_data/reader.py,sha256=CNOdxBallUHoRl9CiIBNi9m9yhYvptQ_tqBsgStMSLY,36078
|
|
7
|
+
shepherd_data/writer.py,sha256=nn5T8pLHbz2FSOfD8yEPvGJLkzrmCcbwitCO0BK9kKc,13261
|
|
8
|
+
shepherd_data-2023.3.1.dist-info/LICENSE,sha256=_d1BhE98zOhkxahuCifG6l34LjhJanVunxp5-QMQHpE,1069
|
|
9
|
+
shepherd_data-2023.3.1.dist-info/METADATA,sha256=AgWVKXvxQU9PPKERT62HsAR_uVWaDgHBj8kFIJQMQq8,12217
|
|
10
|
+
shepherd_data-2023.3.1.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
11
|
+
shepherd_data-2023.3.1.dist-info/entry_points.txt,sha256=6PBfY36A1xNOdzLiz-Qoukya_UzFZAwOapwmRNnPeZ8,56
|
|
12
|
+
shepherd_data-2023.3.1.dist-info/top_level.txt,sha256=7-SCTY-TG1mLY72OVKCaqte1hy-X8woxknIUAD3OIxs,14
|
|
13
|
+
shepherd_data-2023.3.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
14
|
+
shepherd_data-2023.3.1.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
shepherd_data/__init__.py,sha256=vOcsbuxOTwP1PrLgvd33c_dt8Cu5sXvJvrUNJV0SARA,337
|
|
2
|
-
shepherd_data/calibration.py,sha256=j9iEm9XNSI4Z8O3hrCuFqupoOBczdNOhnDIzywWtnrQ,1387
|
|
3
|
-
shepherd_data/cli.py,sha256=lmFJi_qMRQu9oArBnOwbFmazqvpD4Z-urYojZWfeqYc,10435
|
|
4
|
-
shepherd_data/ivonne.py,sha256=q8kscQCerJ81f10_wXPsN1GdM6jnemfY7vra28e_2FM,11111
|
|
5
|
-
shepherd_data/mppt.py,sha256=X8kKB4x8J8xwn3peIUG12fEtGybyGABf5CA9a6poJhc,3487
|
|
6
|
-
shepherd_data/reader.py,sha256=6I_A_agALqi7DwTYgNpHjPjLuJjmAdDAsZK-DnY46aY,34366
|
|
7
|
-
shepherd_data/writer.py,sha256=51fsSsTkJl8-1KIYgclp6Jwtqjj6V0njVb26lSCqqZU,12536
|
|
8
|
-
shepherd_data-2023.2.1.dist-info/LICENSE,sha256=_d1BhE98zOhkxahuCifG6l34LjhJanVunxp5-QMQHpE,1069
|
|
9
|
-
shepherd_data-2023.2.1.dist-info/METADATA,sha256=-wz_vWdMDABNDXajtswFiCqO2lVBcpYYk12wGrA2HwY,11944
|
|
10
|
-
shepherd_data-2023.2.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
|
11
|
-
shepherd_data-2023.2.1.dist-info/entry_points.txt,sha256=6PBfY36A1xNOdzLiz-Qoukya_UzFZAwOapwmRNnPeZ8,56
|
|
12
|
-
shepherd_data-2023.2.1.dist-info/top_level.txt,sha256=7-SCTY-TG1mLY72OVKCaqte1hy-X8woxknIUAD3OIxs,14
|
|
13
|
-
shepherd_data-2023.2.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
14
|
-
shepherd_data-2023.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|