shepherd-data 2025.10.1__tar.gz → 2026.2.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.
Files changed (29) hide show
  1. shepherd_data-2026.2.1/LICENSE +21 -0
  2. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/PKG-INFO +6 -4
  3. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/pyproject.toml +5 -14
  4. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/shepherd_data/__init__.py +1 -1
  5. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/shepherd_data/cli.py +5 -8
  6. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/shepherd_data/mppt.py +11 -5
  7. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/shepherd_data/reader.py +22 -22
  8. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/shepherd_data.egg-info/PKG-INFO +6 -4
  9. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/shepherd_data.egg-info/SOURCES.txt +1 -0
  10. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/shepherd_data.egg-info/requires.txt +1 -1
  11. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/tests/test_ivonne.py +6 -5
  12. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/README.md +0 -0
  13. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/setup.cfg +0 -0
  14. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/shepherd_data/ivonne.py +0 -0
  15. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/shepherd_data.egg-info/dependency_links.txt +0 -0
  16. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/shepherd_data.egg-info/entry_points.txt +0 -0
  17. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/shepherd_data.egg-info/top_level.txt +0 -0
  18. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/shepherd_data.egg-info/zip-safe +0 -0
  19. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/tests/test_cli.py +0 -0
  20. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/tests/test_cli_downsample.py +0 -0
  21. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/tests/test_cli_extract.py +0 -0
  22. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/tests/test_cli_extract_gpio.py +0 -0
  23. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/tests/test_cli_extract_meta.py +0 -0
  24. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/tests/test_cli_extract_uart.py +0 -0
  25. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/tests/test_cli_plot.py +0 -0
  26. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/tests/test_cli_validate.py +0 -0
  27. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/tests/test_cli_version.py +0 -0
  28. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/tests/test_examples.py +0 -0
  29. {shepherd_data-2025.10.1 → shepherd_data-2026.2.1}/tests/test_reader.py +0 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022-2025, Networked Embedded Systems Lab, TU Dresden, Ingmar Splitt
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.
@@ -1,9 +1,10 @@
1
1
  Metadata-Version: 2.4
2
- Name: shepherd_data
3
- Version: 2025.10.1
2
+ Name: shepherd-data
3
+ Version: 2026.2.1
4
4
  Summary: Programming- and CLI-Interface for the h5-dataformat of the Shepherd-Testbed
5
5
  Author-email: Ingmar Splitt <ingmar.splitt@tu-dresden.de>
6
6
  Maintainer-email: Ingmar Splitt <ingmar.splitt@tu-dresden.de>
7
+ License-Expression: MIT
7
8
  Project-URL: Documentation, https://github.com/nes-lab/shepherd-tools/blob/main/README.md
8
9
  Project-URL: Issues, https://pypi.org/project/shepherd-data/issues
9
10
  Project-URL: Source, https://pypi.org/project/shepherd-data/
@@ -23,11 +24,11 @@ Classifier: Programming Language :: Python :: 3.11
23
24
  Classifier: Programming Language :: Python :: 3.12
24
25
  Classifier: Programming Language :: Python :: 3.13
25
26
  Classifier: Programming Language :: Python :: 3.14
26
- Classifier: License :: OSI Approved :: MIT License
27
27
  Classifier: Operating System :: OS Independent
28
28
  Classifier: Natural Language :: English
29
29
  Requires-Python: >=3.10
30
30
  Description-Content-Type: text/markdown
31
+ License-File: LICENSE
31
32
  Requires-Dist: click
32
33
  Requires-Dist: h5py
33
34
  Requires-Dist: matplotlib
@@ -35,7 +36,7 @@ Requires-Dist: numpy
35
36
  Requires-Dist: pandas>=2.0.0
36
37
  Requires-Dist: pyYAML
37
38
  Requires-Dist: scipy
38
- Requires-Dist: shepherd-core[inventory]>=2025.09.1
39
+ Requires-Dist: shepherd-core[inventory]==2026.02.1
39
40
  Requires-Dist: tqdm
40
41
  Provides-Extra: elf
41
42
  Requires-Dist: shepherd-core[elf]; extra == "elf"
@@ -49,6 +50,7 @@ Requires-Dist: pytest-click; extra == "test"
49
50
  Requires-Dist: coverage; extra == "test"
50
51
  Provides-Extra: all
51
52
  Requires-Dist: shepherd-data[dev,elf,test]; extra == "all"
53
+ Dynamic: license-file
52
54
 
53
55
  # Shepherd-Data-Tool
54
56
 
@@ -1,5 +1,5 @@
1
1
  [project]
2
- name = "shepherd_data"
2
+ name = "shepherd-data"
3
3
  description = "Programming- and CLI-Interface for the h5-dataformat of the Shepherd-Testbed"
4
4
  keywords = ["testbed", "beaglebone", "pru", "batteryless", "energyharvesting", "solar"]
5
5
 
@@ -10,7 +10,8 @@ maintainers = [
10
10
  {name = "Ingmar Splitt", email = "ingmar.splitt@tu-dresden.de"},
11
11
  ]
12
12
 
13
- license = {file = "LICENSE"}
13
+ license = "MIT"
14
+ license-files = ["LICENSE"] # can't be in parent dir
14
15
  dynamic = ["version"]
15
16
 
16
17
  classifiers = [
@@ -23,7 +24,6 @@ classifiers = [
23
24
  "Programming Language :: Python :: 3.12",
24
25
  "Programming Language :: Python :: 3.13",
25
26
  "Programming Language :: Python :: 3.14",
26
- "License :: OSI Approved :: MIT License",
27
27
  "Operating System :: OS Independent",
28
28
  "Natural Language :: English",
29
29
  ]
@@ -37,7 +37,7 @@ dependencies = [
37
37
  "pandas>=2.0.0", # full-version, v2 is OK
38
38
  "pyYAML",
39
39
  "scipy", # full-version
40
- "shepherd-core[inventory]>=2025.09.1", # libs are strongly coupled
40
+ "shepherd-core[inventory]==2026.02.1", # libs are strongly coupled
41
41
  "tqdm", # full-version
42
42
  ]
43
43
 
@@ -48,7 +48,7 @@ elf = [
48
48
 
49
49
  dev = [
50
50
  "shepherd-core[dev]",
51
- "pandas-stubs", # for pyright with pandas
51
+ "pandas-stubs", # for type-checkers
52
52
  ]
53
53
 
54
54
  test = [
@@ -99,12 +99,3 @@ addopts = "-vvv --stepwise" # opts: verbose result for each tests
99
99
 
100
100
  [tool.coverage.run]
101
101
  source = ["shepherd_data"]
102
-
103
- [tool.mypy]
104
- python_version = 3.10
105
- ignore_missing_imports = true
106
- disable_error_code = ["call-arg", ]
107
- exclude = [
108
- "build/",
109
- ".egg-info/",
110
- ]
@@ -11,7 +11,7 @@ from shepherd_core import Writer
11
11
 
12
12
  from .reader import Reader
13
13
 
14
- __version__ = "2025.10.1"
14
+ __version__ = "2026.02.1"
15
15
 
16
16
  __all__ = [
17
17
  "Reader",
@@ -58,12 +58,9 @@ def version() -> None:
58
58
  from importlib import metadata # noqa: PLC0415
59
59
 
60
60
  logger.debug("Python v%s", sys.version)
61
- logger.info("Shepherd-Data v%s", metadata.version("shepherd_data"))
62
- logger.debug("Shepherd-Core v%s", metadata.version("shepherd_core"))
63
- logger.debug("h5py v%s", metadata.version("h5py"))
64
- logger.debug("numpy v%s", metadata.version("numpy"))
65
- logger.debug("Click v%s", metadata.version("click"))
66
- logger.debug("Pydantic v%s", metadata.version("pydantic"))
61
+ logger.info("shepherd-data v%s", metadata.version("shepherd_data"))
62
+ for package in ["shepherd_core", "h5py", "numpy", "click", "pydantic"]:
63
+ logger.debug("%s v%s", package, metadata.version(package))
67
64
 
68
65
 
69
66
  @cli.command(short_help="Validates a file or directory containing shepherd-recordings")
@@ -376,8 +373,8 @@ def downsample(
376
373
  else:
377
374
  ds_list = [5, 25, 100, 500, 2_500, 10_000, 50_000, 250_000, 1_000_000]
378
375
 
379
- for _factor in ds_list:
380
- path_file = shpr.cut_and_downsample_to_file(start, end, _factor)
376
+ for factor_ in ds_list:
377
+ path_file = shpr.cut_and_downsample_to_file(start, end, factor_)
381
378
  logger.info("Created %s", path_file.name)
382
379
  except (TypeError, ValueError): # noqa: PERF203
383
380
  logger.exception("ERROR: Will skip file. It caused an exception.")
@@ -15,9 +15,12 @@ from shepherd_core import Calc_t
15
15
  def iv_model(voltages: Calc_t, coeffs: pd.Series) -> Calc_t:
16
16
  """Calculate simple diode based model (equivalent circuit diagram) of a solar panel IV curve.
17
17
 
18
- :param voltages: Load voltage of the solar panel
19
- :param coeffs: three generic coefficients
20
- :return: Solar current at given load voltage
18
+ Args:
19
+ voltages: Load voltage of the solar panel
20
+ coeffs: three generic coefficients
21
+
22
+ Returns:
23
+ Solar current at given load voltage
21
24
  """
22
25
  currents = float(coeffs["a"]) - float(coeffs["b"]) * (
23
26
  np.exp(float(coeffs["c"]) * voltages) - 1.0
@@ -75,8 +78,11 @@ class OpenCircuitTracker(MPPTracker):
75
78
  def process(self, coeffs: pd.DataFrame) -> pd.DataFrame:
76
79
  """Apply harvesting model to input data.
77
80
 
78
- :param coeffs: ivonne coefficients
79
- :return: ivtrace-data
81
+ Args:
82
+ coeffs: ivonne coefficients
83
+
84
+ Returns:
85
+ ivtrace-data
80
86
  """
81
87
  coeffs["icurve"] = coeffs.apply(lambda x: iv_model(self.v_proto, x), axis=1)
82
88
  if "voc" not in coeffs.columns:
@@ -133,45 +133,45 @@ class Reader(CoreReader):
133
133
  show: bool = True,
134
134
  ) -> int:
135
135
  """Print warning messages from log in data-group."""
136
- _count = self.count_errors_in_log(group_name, min_level)
137
- if (_count < 1) or ("level" not in self.h5file[group_name]):
136
+ count = self.count_errors_in_log(group_name, min_level)
137
+ if (count < 1) or ("level" not in self.h5file[group_name]):
138
138
  return 0
139
139
  if not show:
140
- return _count
140
+ return count
141
141
  self._logger.warning(
142
142
  "%s caught %d messages with level>=%d -> first %d are:",
143
143
  self.get_hostname(),
144
- _count,
144
+ count,
145
145
  min_level,
146
146
  limit,
147
147
  )
148
148
  for idx, time_ns in enumerate(self.h5file[group_name]["time"][:]):
149
- _level = self.h5file[group_name]["level"][idx]
150
- if _level < min_level:
149
+ level_ = self.h5file[group_name]["level"][idx]
150
+ if level_ < min_level:
151
151
  continue
152
- _msg = self.h5file[group_name]["message"][idx]
153
- _timestamp = datetime.fromtimestamp(time_ns / 1e9, local_tz())
154
- if _level < 30:
155
- self._logger.info(" %s: %s", _timestamp, _msg)
156
- elif _level < 40:
157
- self._logger.warning(" %s: %s", _timestamp, _msg)
152
+ msg_ = self.h5file[group_name]["message"][idx]
153
+ timestamp_ = datetime.fromtimestamp(time_ns / 1e9, local_tz())
154
+ if level_ < 30:
155
+ self._logger.info(" %s: %s", timestamp_, msg_)
156
+ elif level_ < 40:
157
+ self._logger.warning(" %s: %s", timestamp_, msg_)
158
158
  else:
159
- self._logger.error(" %s: %s", _timestamp, _msg)
159
+ self._logger.error(" %s: %s", timestamp_, msg_)
160
160
  limit -= 1
161
161
  if limit < 1:
162
162
  break
163
- return _count
163
+ return count
164
164
 
165
165
  def downsample(
166
166
  self,
167
167
  data_src: h5py.Dataset | np.ndarray,
168
- data_dst: None | h5py.Dataset | np.ndarray,
168
+ data_dst: h5py.Dataset | np.ndarray | None,
169
169
  start_n: int = 0,
170
170
  end_n: int | None = None,
171
171
  ds_factor: float = 5,
172
172
  *,
173
173
  is_time: bool = False,
174
- ) -> None | h5py.Dataset | np.ndarray:
174
+ ) -> h5py.Dataset | np.ndarray | None:
175
175
  """Sample down iv-data.
176
176
 
177
177
  Warning: only valid for IV-Stream, not IV-Curves,
@@ -233,7 +233,7 @@ class Reader(CoreReader):
233
233
  slice_ds, f_state = signal.sosfilt(filter_, slice_ds, zi=f_state)
234
234
 
235
235
  output_pos = 0
236
- for _iter in trange(
236
+ for iter_ in trange(
237
237
  0,
238
238
  iterations,
239
239
  desc=f"downsampling {data_src.name if isinstance(data_src, h5py.Dataset) else ''}",
@@ -241,12 +241,12 @@ class Reader(CoreReader):
241
241
  disable=iterations < 8,
242
242
  ):
243
243
  slice_ds = data_src[
244
- start_n + _iter * chunk_size_inp : start_n + (_iter + 1) * chunk_size_inp
244
+ start_n + iter_ * chunk_size_inp : start_n + (iter_ + 1) * chunk_size_inp
245
245
  ]
246
246
  if not is_time and ds_factor > 1:
247
247
  slice_ds, f_state = signal.sosfilt(filter_, slice_ds, zi=f_state)
248
248
  slice_ds = slice_ds[::ds_factor]
249
- slice_len = min(dest_len - _iter * chunk_size_out, chunk_size_out, len(slice_ds))
249
+ slice_len = min(dest_len - iter_ * chunk_size_out, chunk_size_out, len(slice_ds))
250
250
  data_dst[output_pos : output_pos + slice_len] = slice_ds[:slice_len]
251
251
  # workaround to allow processing last slice (often smaller than expected),
252
252
  # wanted: [_iter * chunk_size_out : (_iter + 1) * chunk_size_out]
@@ -363,13 +363,13 @@ class Reader(CoreReader):
363
363
  def resample(
364
364
  self,
365
365
  data_src: h5py.Dataset | np.ndarray,
366
- data_dst: None | h5py.Dataset | np.ndarray,
366
+ data_dst: h5py.Dataset | np.ndarray | None,
367
367
  start_n: int = 0,
368
368
  end_n: int | None = None,
369
369
  samplerate_dst: float = 1000,
370
370
  *,
371
371
  is_time: bool = False,
372
- ) -> None | h5py.Dataset | np.ndarray:
372
+ ) -> h5py.Dataset | np.ndarray | None:
373
373
  """Up- or down-sample the original trace-data.
374
374
 
375
375
  :param data_src: original iv-data
@@ -518,7 +518,7 @@ class Reader(CoreReader):
518
518
  "end_s": end_s,
519
519
  }
520
520
  if relative_timestamp:
521
- data["time"] = data["time"] - self._cal.time.raw_to_si(self.ds_time[0])
521
+ data["time"] -= self._cal.time.raw_to_si(self.ds_time[0])
522
522
  return data
523
523
 
524
524
  @staticmethod
@@ -1,9 +1,10 @@
1
1
  Metadata-Version: 2.4
2
- Name: shepherd_data
3
- Version: 2025.10.1
2
+ Name: shepherd-data
3
+ Version: 2026.2.1
4
4
  Summary: Programming- and CLI-Interface for the h5-dataformat of the Shepherd-Testbed
5
5
  Author-email: Ingmar Splitt <ingmar.splitt@tu-dresden.de>
6
6
  Maintainer-email: Ingmar Splitt <ingmar.splitt@tu-dresden.de>
7
+ License-Expression: MIT
7
8
  Project-URL: Documentation, https://github.com/nes-lab/shepherd-tools/blob/main/README.md
8
9
  Project-URL: Issues, https://pypi.org/project/shepherd-data/issues
9
10
  Project-URL: Source, https://pypi.org/project/shepherd-data/
@@ -23,11 +24,11 @@ Classifier: Programming Language :: Python :: 3.11
23
24
  Classifier: Programming Language :: Python :: 3.12
24
25
  Classifier: Programming Language :: Python :: 3.13
25
26
  Classifier: Programming Language :: Python :: 3.14
26
- Classifier: License :: OSI Approved :: MIT License
27
27
  Classifier: Operating System :: OS Independent
28
28
  Classifier: Natural Language :: English
29
29
  Requires-Python: >=3.10
30
30
  Description-Content-Type: text/markdown
31
+ License-File: LICENSE
31
32
  Requires-Dist: click
32
33
  Requires-Dist: h5py
33
34
  Requires-Dist: matplotlib
@@ -35,7 +36,7 @@ Requires-Dist: numpy
35
36
  Requires-Dist: pandas>=2.0.0
36
37
  Requires-Dist: pyYAML
37
38
  Requires-Dist: scipy
38
- Requires-Dist: shepherd-core[inventory]>=2025.09.1
39
+ Requires-Dist: shepherd-core[inventory]==2026.02.1
39
40
  Requires-Dist: tqdm
40
41
  Provides-Extra: elf
41
42
  Requires-Dist: shepherd-core[elf]; extra == "elf"
@@ -49,6 +50,7 @@ Requires-Dist: pytest-click; extra == "test"
49
50
  Requires-Dist: coverage; extra == "test"
50
51
  Provides-Extra: all
51
52
  Requires-Dist: shepherd-data[dev,elf,test]; extra == "all"
53
+ Dynamic: license-file
52
54
 
53
55
  # Shepherd-Data-Tool
54
56
 
@@ -1,3 +1,4 @@
1
+ LICENSE
1
2
  README.md
2
3
  pyproject.toml
3
4
  shepherd_data/__init__.py
@@ -5,7 +5,7 @@ numpy
5
5
  pandas>=2.0.0
6
6
  pyYAML
7
7
  scipy
8
- shepherd-core[inventory]>=2025.09.1
8
+ shepherd-core[inventory]==2026.02.1
9
9
  tqdm
10
10
 
11
11
  [all]
@@ -20,21 +20,22 @@ def test_convert_ivonne(tmp_path: Path, example_path: Path) -> None:
20
20
  ivc_path = tmp_path / (input_file + "_ivc.h5")
21
21
  voc_path = tmp_path / (input_file + "_voc.h5")
22
22
  opt_path = tmp_path / (input_file + "_opt.h5")
23
+ duration = 6
23
24
 
24
25
  with ivonne.Reader(inp_path) as ifr:
25
- ifr.upsample_2_isc_voc(isc_path, duration_s=20)
26
- ifr.convert_2_ivsurface(ivc_path, duration_s=20)
26
+ ifr.upsample_2_isc_voc(isc_path, duration_s=duration)
27
+ ifr.convert_2_ivsurface(ivc_path, duration_s=duration)
27
28
 
28
29
  tr_voc = mppt.OpenCircuitTracker(ratio=0.76)
29
30
  tr_opt = mppt.OptimalTracker()
30
31
 
31
- ifr.convert_2_ivtrace(voc_path, tracker=tr_voc, duration_s=20)
32
- ifr.convert_2_ivtrace(opt_path, tracker=tr_opt, duration_s=20)
32
+ ifr.convert_2_ivtrace(voc_path, tracker=tr_voc, duration_s=duration)
33
+ ifr.convert_2_ivtrace(opt_path, tracker=tr_opt, duration_s=duration)
33
34
 
34
35
  energies = {}
35
36
  for file_path in [isc_path, ivc_path, voc_path, opt_path]:
36
37
  with Reader(file_path) as sfr:
37
- assert sfr.runtime_s == 20
38
+ assert sfr.runtime_s == duration
38
39
  energies[file_path.stem[-3:]] = sfr.energy()
39
40
 
40
41
  assert energies["isc"] > energies["opt"]