shepherd-data 2024.7.3__tar.gz → 2024.8.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 (24) hide show
  1. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/PKG-INFO +2 -2
  2. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/pyproject.toml +1 -1
  3. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/shepherd_data/__init__.py +1 -1
  4. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/shepherd_data/cli.py +12 -4
  5. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/shepherd_data/reader.py +45 -19
  6. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/shepherd_data.egg-info/PKG-INFO +2 -2
  7. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/shepherd_data.egg-info/requires.txt +1 -1
  8. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/README.md +0 -0
  9. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/setup.cfg +0 -0
  10. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/shepherd_data/ivonne.py +0 -0
  11. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/shepherd_data/mppt.py +0 -0
  12. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/shepherd_data.egg-info/SOURCES.txt +0 -0
  13. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/shepherd_data.egg-info/dependency_links.txt +0 -0
  14. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/shepherd_data.egg-info/entry_points.txt +0 -0
  15. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/shepherd_data.egg-info/top_level.txt +0 -0
  16. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/shepherd_data.egg-info/zip-safe +0 -0
  17. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/tests/test_cli.py +0 -0
  18. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/tests/test_cli_downsample.py +0 -0
  19. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/tests/test_cli_extract.py +0 -0
  20. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/tests/test_cli_plot.py +0 -0
  21. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/tests/test_cli_validate.py +0 -0
  22. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/tests/test_examples.py +0 -0
  23. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/tests/test_ivonne.py +0 -0
  24. {shepherd_data-2024.7.3 → shepherd_data-2024.8.1}/tests/test_reader.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: shepherd_data
3
- Version: 2024.7.3
3
+ Version: 2024.8.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>
@@ -35,7 +35,7 @@ Requires-Dist: numpy
35
35
  Requires-Dist: pandas>=2.0.0
36
36
  Requires-Dist: pyYAML
37
37
  Requires-Dist: scipy
38
- Requires-Dist: shepherd-core[inventory]>=2024.7.3
38
+ Requires-Dist: shepherd-core[inventory]>=2024.8.1
39
39
  Requires-Dist: tqdm
40
40
  Provides-Extra: elf
41
41
  Requires-Dist: shepherd-core[elf]; extra == "elf"
@@ -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]>=2024.7.3",
40
+ "shepherd-core[inventory]>=2024.8.1",
41
41
  "tqdm", # full-version
42
42
  ]
43
43
 
@@ -11,7 +11,7 @@ from shepherd_core import Writer
11
11
 
12
12
  from .reader import Reader
13
13
 
14
- __version__ = "2024.7.3"
14
+ __version__ = "2024.8.1"
15
15
 
16
16
  __all__ = [
17
17
  "Reader",
@@ -58,7 +58,7 @@ def path_to_flist(data_path: Path) -> List[Path]:
58
58
  help="Prints version-info at start (combinable with -v)",
59
59
  )
60
60
  @click.pass_context # TODO: is the ctx-type correct?
61
- def cli(ctx: click.Context, verbose: bool, version: bool) -> None: # noqa: FBT001
61
+ def cli(ctx: click.Context, *, verbose: bool, version: bool) -> None:
62
62
  """Shepherd: Synchronized Energy Harvesting Emulator and Recorder."""
63
63
  if verbose:
64
64
  increase_verbose_level(3)
@@ -355,13 +355,21 @@ def downsample(in_data: Path, ds_factor: Optional[float], sample_rate: Optional[
355
355
  is_flag=True,
356
356
  help="Plot all files (in directory) into one Multiplot",
357
357
  )
358
+ @click.option(
359
+ "--only-power",
360
+ "-p",
361
+ is_flag=True,
362
+ help="Plot only power instead of voltage, current & power",
363
+ )
358
364
  def plot(
359
365
  in_data: Path,
360
366
  start: Optional[float],
361
367
  end: Optional[float],
362
368
  width: int,
363
369
  height: int,
364
- multiplot: bool, # noqa: FBT001
370
+ *,
371
+ multiplot: bool,
372
+ only_power: bool,
365
373
  ) -> None:
366
374
  """Plot IV-trace from file or directory containing shepherd-recordings."""
367
375
  files = path_to_flist(in_data)
@@ -378,12 +386,12 @@ def plot(
378
386
  continue
379
387
  data.append(date)
380
388
  else:
381
- shpr.plot_to_file(start, end, width, height)
389
+ shpr.plot_to_file(start, end, width, height, only_pwr=only_power)
382
390
  except TypeError:
383
391
  logger.exception("ERROR: Will skip file. It caused an exception.")
384
392
  if multiplot:
385
393
  logger.info("Got %d datasets to plot", len(data))
386
- mpl_path = Reader.multiplot_to_file(data, in_data, width, height)
394
+ mpl_path = Reader.multiplot_to_file(data, in_data, width, height, only_pwr=only_power)
387
395
  if mpl_path:
388
396
  logger.info("Plot generated and saved to '%s'", mpl_path.name)
389
397
  else:
@@ -171,7 +171,6 @@ class Reader(CoreReader):
171
171
 
172
172
  if self.get_datatype() == "ivcurve":
173
173
  self._logger.warning("Downsampling-Function was not written for IVCurves")
174
- return data_dst
175
174
  ds_factor = max(1, math.floor(ds_factor))
176
175
 
177
176
  if isinstance(end_n, (int, float)):
@@ -345,7 +344,6 @@ class Reader(CoreReader):
345
344
  """
346
345
  if self.get_datatype() == "ivcurve":
347
346
  self._logger.warning("Plot-Function was not written for IVCurves.")
348
- return None
349
347
  if not isinstance(start_s, (float, int)):
350
348
  start_s = 0
351
349
  if not isinstance(end_s, (float, int)):
@@ -357,7 +355,7 @@ class Reader(CoreReader):
357
355
  return None
358
356
  samplerate_dst = max(round(self.max_elements / (end_s - start_s), 3), 0.001)
359
357
  ds_factor = float(self.samplerate_sps / samplerate_dst)
360
- data = {
358
+ data: dict = {
361
359
  "name": self.get_hostname(),
362
360
  "time": self._cal.time.raw_to_si(
363
361
  self.downsample(
@@ -383,31 +381,50 @@ class Reader(CoreReader):
383
381
  return data
384
382
 
385
383
  @staticmethod
386
- def assemble_plot(data: Union[dict, list], width: int = 20, height: int = 10) -> plt.Figure:
384
+ def assemble_plot(
385
+ data: Union[dict, list], width: int = 20, height: int = 10, *, only_pwr: bool = False
386
+ ) -> plt.Figure:
387
387
  """Create the actual figure.
388
388
 
389
+ Due to the 50 mA limits of the cape the default units for current & power are mA & mW.
390
+
389
391
  :param data: plottable / down-sampled iv-data with some meta-data
390
392
  -> created with generate_plot_data()
391
393
  :param width: plot-width
392
394
  :param height: plot-height
395
+ :param only_pwr: plot power-trace instead of voltage, current & power
393
396
  :return: figure
394
397
  """
395
- # TODO: add power (if wanted)
398
+ # TODO: allow choosing freely from I, V, P, GPIO
396
399
  if isinstance(data, dict):
397
400
  data = [data]
398
- fig, axes = plt.subplots(2, 1, sharex="all")
399
- fig.suptitle("Voltage and current")
401
+ if only_pwr:
402
+ fig, ax = plt.subplots(1, 1, figsize=(width, height), layout="tight")
403
+ axs = [ax]
404
+ fig.suptitle("Power-Trace")
405
+ else:
406
+ fig, axs = plt.subplots(3, 1, sharex="all", figsize=(width, height), layout="tight")
407
+ fig.suptitle("Voltage, current & power")
408
+ axs[0].set_ylabel("voltage [V]")
409
+ axs[1].set_ylabel("current [mA]")
410
+ # last axis is set below
411
+
400
412
  for date in data:
401
- axes[0].plot(date["time"], date["voltage"], label=date["name"])
402
- axes[1].plot(date["time"], date["current"] * 10**6, label=date["name"])
403
- axes[0].set_ylabel("voltage [V]")
404
- axes[1].set_ylabel(r"current [$\mu$A]")
413
+ if not only_pwr:
414
+ axs[0].plot(date["time"], date["voltage"], label=date["name"])
415
+ axs[1].plot(date["time"], date["current"] * 10**3, label=date["name"])
416
+ axs[-1].plot(
417
+ date["time"], date["voltage"] * date["current"] * 10**3, label=date["name"]
418
+ )
419
+
405
420
  if len(data) > 1:
406
- axes[0].legend(loc="lower center", ncol=len(data))
407
- axes[1].set_xlabel("time [s]")
408
- fig.set_figwidth(width)
409
- fig.set_figheight(height)
410
- fig.tight_layout()
421
+ axs[0].legend(loc="lower center", ncol=len(data))
422
+ axs[-1].set_xlabel("time [s]")
423
+ axs[-1].set_ylabel("power [mW]")
424
+ for ax in axs:
425
+ # deactivates offset-creation for ax-ticks
426
+ ax.get_yaxis().get_major_formatter().set_useOffset(False)
427
+ ax.get_xaxis().get_major_formatter().set_useOffset(False)
411
428
  return fig
412
429
 
413
430
  def plot_to_file(
@@ -416,6 +433,8 @@ class Reader(CoreReader):
416
433
  end_s: Optional[float] = None,
417
434
  width: int = 20,
418
435
  height: int = 10,
436
+ *,
437
+ only_pwr: bool = False,
419
438
  ) -> None:
420
439
  """Create (down-sampled) IV-Plots.
421
440
 
@@ -425,6 +444,7 @@ class Reader(CoreReader):
425
444
  :param end_s: time in seconds, relative to start of recording, optional
426
445
  :param width: plot-width
427
446
  :param height: plot-height
447
+ :param only_pwr: plot power-trace instead of voltage, current & power
428
448
  """
429
449
  if not isinstance(self.file_path, Path):
430
450
  return
@@ -440,14 +460,19 @@ class Reader(CoreReader):
440
460
  self._logger.warning("Plot exists, will skip & not overwrite!")
441
461
  return
442
462
  self._logger.info("Plot generated, will be saved to '%s'", plot_path.name)
443
- fig = self.assemble_plot(data, width, height)
463
+ fig = self.assemble_plot(data, width, height, only_pwr=only_pwr)
444
464
  plt.savefig(plot_path)
445
465
  plt.close(fig)
446
466
  plt.clf()
447
467
 
448
468
  @staticmethod
449
469
  def multiplot_to_file(
450
- data: list, plot_path: Path, width: int = 20, height: int = 10
470
+ data: list,
471
+ plot_path: Path,
472
+ width: int = 20,
473
+ height: int = 10,
474
+ *,
475
+ only_pwr: bool = False,
451
476
  ) -> Optional[Path]:
452
477
  """Create (down-sampled) IV-Multi-Plots (of more than one trace).
453
478
 
@@ -456,6 +481,7 @@ class Reader(CoreReader):
456
481
  :param plot_path: optional
457
482
  :param width: plot-width
458
483
  :param height: plot-height
484
+ :param only_pwr: plot power-trace instead of voltage, current & power
459
485
  """
460
486
  start_str = f"{data[0]['start_s']:.3f}".replace(".", "s")
461
487
  end_str = f"{data[0]['end_s']:.3f}".replace(".", "s")
@@ -465,7 +491,7 @@ class Reader(CoreReader):
465
491
  if plot_path.exists():
466
492
  logger.warning("Plot exists, will skip & not overwrite!")
467
493
  return None
468
- fig = Reader.assemble_plot(data, width, height)
494
+ fig = Reader.assemble_plot(data, width, height, only_pwr=only_pwr)
469
495
  plt.savefig(plot_path)
470
496
  plt.close(fig)
471
497
  plt.clf()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: shepherd_data
3
- Version: 2024.7.3
3
+ Version: 2024.8.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>
@@ -35,7 +35,7 @@ Requires-Dist: numpy
35
35
  Requires-Dist: pandas>=2.0.0
36
36
  Requires-Dist: pyYAML
37
37
  Requires-Dist: scipy
38
- Requires-Dist: shepherd-core[inventory]>=2024.7.3
38
+ Requires-Dist: shepherd-core[inventory]>=2024.8.1
39
39
  Requires-Dist: tqdm
40
40
  Provides-Extra: elf
41
41
  Requires-Dist: shepherd-core[elf]; extra == "elf"
@@ -5,7 +5,7 @@ numpy
5
5
  pandas>=2.0.0
6
6
  pyYAML
7
7
  scipy
8
- shepherd-core[inventory]>=2024.7.3
8
+ shepherd-core[inventory]>=2024.8.1
9
9
  tqdm
10
10
 
11
11
  [dev]