shepherd-data 2022.9.3__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/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 verbose is not None:
85
- self._logger.setLevel(logging.INFO if verbose else logging.WARNING)
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"can not handle type '{type(mode)}' for mode")
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(f"can not handle mode '{mode}'")
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(f"can not handle type '{type(datatype)}' for datatype")
106
- if (
107
- isinstance(datatype, str)
108
- and datatype
109
- not in self.mode_dtype_dict[self.mode_default if (mode is None) else mode]
110
- ):
111
- raise ValueError(f"can not handle datatype '{datatype}'")
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 = cal_data
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 = self.mode_default if (mode is None) else mode
120
- self._cal = cal_default if (cal_data is None) else cal_data
121
- self._datatype = self.datatype_default if (datatype is None) else datatype
122
- self._window_samples = 0 if (window_samples is None) else window_samples
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
- def __enter__(self):
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
- ) -> NoReturn:
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.array,
270
- ) -> NoReturn:
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) -> NoReturn:
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) -> NoReturn:
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) -> NoReturn:
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) -> NoReturn:
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: 2022.9.3
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
@@ -20,15 +20,15 @@ Classifier: Development Status :: 5 - Production/Stable
20
20
  Classifier: Intended Audience :: Developers
21
21
  Classifier: Intended Audience :: Information Technology
22
22
  Classifier: Intended Audience :: Science/Research
23
- Classifier: Programming Language :: Python :: 3.6
24
23
  Classifier: Programming Language :: Python :: 3.7
25
24
  Classifier: Programming Language :: Python :: 3.8
26
25
  Classifier: Programming Language :: Python :: 3.9
27
26
  Classifier: Programming Language :: Python :: 3.10
27
+ Classifier: Programming Language :: Python :: 3.11
28
28
  Classifier: License :: OSI Approved :: MIT License
29
29
  Classifier: Operating System :: OS Independent
30
30
  Classifier: Natural Language :: English
31
- Requires-Python: >=3.6
31
+ Requires-Python: >=3.7
32
32
  Description-Content-Type: text/markdown
33
33
  License-File: LICENSE
34
34
  Requires-Dist: click
@@ -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
  [![PyPiVersion](https://img.shields.io/pypi/v/shepherd_data.svg)](https://pypi.org/project/shepherd_data)
54
58
  [![Pytest](https://github.com/orgua/shepherd-datalib/actions/workflows/python-app.yml/badge.svg)](https://github.com/orgua/shepherd-datalib/actions/workflows/python-app.yml)
55
59
  [![CodeStyle](https://img.shields.io/badge/code%20style-black-000000.svg)](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
- ### Installation
63
+ ---
62
64
 
63
- #### PIP - Online
65
+ **Main Project**: [https://github.com/orgua/shepherd](https://github.com/orgua/shepherd)
64
66
 
65
- ```Shell
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
- #### PIP - Offline
79
+ ### PIP - Offline
70
80
 
71
81
  - clone repository
72
82
  - navigate shell into directory
73
83
  - install local module
74
84
 
75
- ```Shell
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
- ### Development
92
+ ## Development
83
93
 
84
- #### PipEnv
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
- #### running Testbench
116
+ ### running Testbench
107
117
 
108
118
  - run pytest
109
119
 
110
- ```Shell
120
+ ```shell
111
121
  pytest
112
122
  ```
113
123
 
114
- #### code coverage (with pytest)
124
+ ### code coverage (with pytest)
115
125
 
116
126
  - run coverage
117
127
  - check results (in browser `./htmlcov/index.html`)
118
128
 
119
- ```Shell
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
- ### Programming Interface
137
+ ## Programming Interface
128
138
 
129
- #### Basic Usage (recommendation)
139
+ ### Basic Usage (recommendation)
130
140
 
131
- ```Python
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
- #### Available Functionality
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
- ### CLI-Interface
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
- ```Shell
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
- ```Shell
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
- ```Shell
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
- ```Shell
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
- ```Shell
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
- ### Data-Layout and Design choices
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
- #### Modes and Datatypes
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
- #### Compression & Beaglebone
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,15 +294,23 @@ 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
- ### Release-Procedure
297
+ ## Release-Procedure
288
298
 
289
299
  - increase version number in __init__.py
300
+ - install and run pre-commit, for QA-Checks, see steps below
290
301
  - every commit get automatically tested by Github
291
302
  - put together a release on Github - the tag should match current version-number
292
303
  - Github automatically pushes release to pypi
293
304
 
294
- ### Open Tasks
305
+ ```shell
306
+ pip3 install pre-commit
307
+
308
+ pre-commit run --all-files
309
+ ```
310
+
311
+ ## Open Tasks
295
312
 
313
+ - [click progressbar](https://click.palletsprojects.com/en/8.1.x/api/#click.progressbar) -> could replace tqdm
296
314
  - implementations for this lib
297
315
  - generalize up- and down-sampling, use out_sample_rate instead of ds-factor
298
316
  - lib samplerate (tested) -> promising, but designed for float32 and range of +-1.0
@@ -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,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: bdist_wheel (0.40.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ shepherd-data = shepherd_data.cli:cli
@@ -1,14 +0,0 @@
1
- shepherd_data/__init__.py,sha256=zi3OdHWjNfAGKOI-t-sBnAytUSji7VkGucdwh-o5y9c,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=t56nKE5Jxv67W01spd3Z93Az_g5sDjapiNX2h88iRf8,11114
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-2022.9.3.dist-info/LICENSE,sha256=_d1BhE98zOhkxahuCifG6l34LjhJanVunxp5-QMQHpE,1069
9
- shepherd_data-2022.9.3.dist-info/METADATA,sha256=Uv59vFyVi57KS_WvtzT3Eej59vV0bx27kyKu0xSdtIA,11705
10
- shepherd_data-2022.9.3.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
11
- shepherd_data-2022.9.3.dist-info/entry_points.txt,sha256=UMg7kAzLZd4CL-9bgeJCdaklvtBj-BUK3l5ApoTroMA,56
12
- shepherd_data-2022.9.3.dist-info/top_level.txt,sha256=7-SCTY-TG1mLY72OVKCaqte1hy-X8woxknIUAD3OIxs,14
13
- shepherd_data-2022.9.3.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
14
- shepherd_data-2022.9.3.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- shepherd_data = shepherd_data.cli:cli