shepherd-core 2024.9.1__py3-none-any.whl → 2024.11.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.
@@ -102,6 +102,7 @@
102
102
  enable_feedback_to_hrv: true # src can control a cv-harvester for ivcurve
103
103
  V_intermediate_enable_threshold_mV: 2000
104
104
  V_intermediate_disable_threshold_mV: 1800 # nRF draw ~0.5 mA below that point
105
+ # TODO: put switch-output into special nRF Version
105
106
 
106
107
  - datatype: VirtualSourceConfig
107
108
  parameters:
shepherd_core/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """Separated string avoids circular imports."""
2
2
 
3
- version: str = "2024.9.1"
3
+ version: str = "2024.11.1"
@@ -79,10 +79,10 @@ class DiodeTarget(TargetABC):
79
79
 
80
80
  def step(self, voltage_uV: int, *, pwr_good: bool) -> float:
81
81
  if pwr_good or not self.ctrl:
82
- V_CC = voltage_uV * 1e-3
82
+ V_CC = voltage_uV * 1e-6
83
83
  V_D = V_CC / 2
84
84
  I_R = I_D = 0
85
- # there is no direct formular, but this recursion converges fast
85
+ # there is no direct formular, but this iteration converges fast
86
86
  for _ in range(10):
87
87
  # low voltages tend to produce log(x<0)=err
88
88
  with suppress(ValueError):
@@ -90,8 +90,9 @@ class DiodeTarget(TargetABC):
90
90
  # both currents are positive and should be identical
91
91
  I_R = max(0.0, (V_CC - V_D) / self.R_Ohm)
92
92
  I_D = max(0.0, self.I_S * math.expm1(V_D / self.c1))
93
- if abs(I_R / I_D - 1) < 1e-6:
94
- break
93
+ with suppress(ZeroDivisionError):
94
+ if abs(I_R / I_D - 1) < 1e-6:
95
+ break
95
96
  # take mean of both currents and determine a new V_D
96
97
  V_D = V_CC - self.R_Ohm * (I_R + I_D) / 2
97
98
  return 1e9 * (I_R + I_D) / 2 # = nA
@@ -101,7 +101,7 @@ class VirtualConverterModel:
101
101
 
102
102
  # pulled from update_states_and_output() due to easier static init
103
103
  self.sample_count: int = 0xFFFFFFF0
104
- self.is_outputting: bool = True
104
+ self.is_outputting: bool = False
105
105
  self.vsource_skip_gpio_logging: bool = False
106
106
 
107
107
  def calc_inp_power(self, input_voltage_uV: float, input_current_nA: float) -> int:
@@ -180,6 +180,7 @@ class VirtualConverterModel:
180
180
 
181
181
  # TODO: add range-checks for add, sub Ops
182
182
  def update_cap_storage(self) -> int:
183
+ # TODO: this calculation is wrong for everything beside boost-cnv
183
184
  if self.enable_storage:
184
185
  V_mid_prot_uV = max(1.0, self.V_mid_uV)
185
186
  P_sum_fW = self.P_inp_fW - self.P_out_fW
@@ -194,22 +195,24 @@ class VirtualConverterModel:
194
195
  def update_states_and_output(self) -> int:
195
196
  self.sample_count += 1
196
197
  check_thresholds = self.sample_count >= self._cfg.interval_check_thresholds_n
198
+ V_mid_uV_now = self.V_mid_uV
199
+ # copy avoids not enabling pwr_good (due to large dV_enable_output_uV)
197
200
 
198
201
  if check_thresholds:
199
202
  self.sample_count = 0
200
203
  if self.is_outputting:
201
- if self.V_mid_uV < self.V_disable_output_threshold_uV:
204
+ if V_mid_uV_now < self.V_disable_output_threshold_uV:
202
205
  self.is_outputting = False
203
- elif self.V_mid_uV >= self.V_enable_output_threshold_uV:
206
+ elif V_mid_uV_now >= self.V_enable_output_threshold_uV:
204
207
  self.is_outputting = True
205
208
  self.V_mid_uV -= self.dV_enable_output_uV
206
209
 
207
210
  if check_thresholds or self._cfg.immediate_pwr_good_signal:
208
211
  # generate power-good-signal
209
212
  if self.power_good:
210
- if self.V_mid_uV <= self._cfg.V_pwr_good_disable_threshold_uV:
213
+ if V_mid_uV_now <= self._cfg.V_pwr_good_disable_threshold_uV:
211
214
  self.power_good = False
212
- elif self.V_mid_uV >= self._cfg.V_pwr_good_enable_threshold_uV:
215
+ elif V_mid_uV_now >= self._cfg.V_pwr_good_enable_threshold_uV:
213
216
  self.power_good = self.is_outputting
214
217
  # set batok pin to state ... TODO?
215
218
 
@@ -170,8 +170,9 @@ class VirtualHarvesterModel:
170
170
 
171
171
  _voltage_uV, _current_nA = self.ivcurve_2_cv(_voltage_uV, _current_nA)
172
172
  if self.interval_step < self._cfg.duration_n:
173
+ self.voltage_set_uV = self.voc_now
174
+ elif self.interval_step == self._cfg.duration_n:
173
175
  self.voltage_set_uV = int(self.voc_now * self._cfg.setpoint_n8 / 256)
174
- _current_nA = 0
175
176
 
176
177
  return _voltage_uV, _current_nA
177
178
 
shepherd_core/writer.py CHANGED
@@ -94,7 +94,7 @@ class Writer(Reader):
94
94
 
95
95
  comp_default: int = 1
96
96
  mode_default: str = "harvester"
97
- datatype_default: str = EnergyDType.ivsample
97
+ datatype_default: EnergyDType = EnergyDType.ivsample
98
98
 
99
99
  _chunk_shape: tuple = (Reader.samples_per_buffer,)
100
100
 
@@ -137,79 +137,72 @@ class Writer(Reader):
137
137
  self.file_path.name,
138
138
  )
139
139
 
140
+ # open file
141
+ if self._modify:
142
+ self.h5file = h5py.File(self.file_path, "r+") # = rw
143
+ else:
144
+ if not self.file_path.parent.exists():
145
+ self.file_path.parent.mkdir(parents=True)
146
+ self.h5file = h5py.File(self.file_path, "w")
147
+ # ⤷ write, truncate if exist
148
+ self._create_skeleton()
149
+
150
+ # Handle Mode
140
151
  if isinstance(mode, str) and mode not in self.mode_dtype_dict:
141
152
  msg = f"Can't handle mode '{mode}' (choose one of {self.mode_dtype_dict})"
142
153
  raise ValueError(msg)
143
154
 
144
- _dtypes = self.mode_dtype_dict[mode or self.mode_default]
155
+ if mode is not None:
156
+ self.h5file.attrs["mode"] = mode
157
+ if "mode" not in self.h5file.attrs:
158
+ self.h5file.attrs["mode"] = self.mode_default
159
+
160
+ _dtypes = self.mode_dtype_dict[self.get_mode()]
161
+
162
+ # Handle Datatype
145
163
  if isinstance(datatype, str):
146
164
  datatype = EnergyDType[datatype]
147
165
  if isinstance(datatype, EnergyDType) and datatype not in _dtypes:
148
166
  msg = f"Can't handle value '{datatype}' of datatype (choose one of {_dtypes})"
149
167
  raise ValueError(msg)
150
168
 
151
- if self._modify:
152
- if mode:
153
- self._mode = mode
154
- if not hasattr(self, "_mode"):
155
- self._mode = self.mode_default
156
- if datatype:
157
- self._datatype = datatype
158
- if not hasattr(self, "_datatype"):
159
- self._datatype = self.datatype_default
160
- if window_samples:
161
- self._window_samples = window_samples
162
- if not hasattr(self, "_window_samples"):
163
- self._window_samples = 0
164
- else:
165
- self._mode = mode if isinstance(mode, str) else self.mode_default
166
- self._datatype = (
167
- datatype if isinstance(datatype, EnergyDType) else self.datatype_default
169
+ if isinstance(datatype, EnergyDType):
170
+ self.h5file["data"].attrs["datatype"] = datatype.name
171
+ if "datatype" not in self.h5file["data"].attrs:
172
+ self.h5file["data"].attrs["datatype"] = self.datatype_default.name
173
+ if self.get_datatype() not in _dtypes:
174
+ msg = (
175
+ f"Can't handle value '{self.get_datatype()}' of datatype (choose one of {_dtypes})"
168
176
  )
169
- self._window_samples = window_samples if isinstance(window_samples, int) else 0
177
+ raise ValueError(msg)
170
178
 
179
+ # Handle Window_samples
180
+ if window_samples is not None:
181
+ self.h5file["data"].attrs["window_samples"] = window_samples
182
+ if "window_samples" not in self.h5file["data"].attrs:
183
+ self.h5file["data"].attrs["window_samples"] = 0
184
+
185
+ if datatype == EnergyDType.ivcurve and self.get_window_samples() < 1:
186
+ raise ValueError("Window Size argument needed for ivcurve-Datatype")
187
+
188
+ # Handle Cal
171
189
  if isinstance(cal_data, (CalEmu, CalHrv)):
172
- self._cal = CalSeries.from_cal(cal_data)
173
- elif isinstance(cal_data, CalSeries):
174
- self._cal = cal_data
175
- else:
176
- self._cal = CalSeries()
190
+ cal_data = CalSeries.from_cal(cal_data)
177
191
 
178
- # open file
179
- if self._modify:
180
- self.h5file = h5py.File(self.file_path, "r+") # = rw
192
+ if isinstance(cal_data, CalSeries):
193
+ for ds, param in product(["current", "voltage", "time"], ["gain", "offset"]):
194
+ self.h5file["data"][ds].attrs[param] = cal_data[ds][param]
181
195
  else:
182
- if not self.file_path.parent.exists():
183
- self.file_path.parent.mkdir(parents=True)
184
- self.h5file = h5py.File(self.file_path, "w")
185
- # write, truncate if exist
186
- self._create_skeleton()
196
+ # check if there are unset cal-values and set them to default
197
+ cal_data = CalSeries()
198
+ for ds, param in product(["current", "voltage", "time"], ["gain", "offset"]):
199
+ if param not in self.h5file["data"][ds].attrs:
200
+ self.h5file["data"][ds].attrs[param] = cal_data[ds][param]
187
201
 
188
202
  # show key parameters for h5-performance
189
203
  settings = list(self.h5file.id.get_access_plist().get_cache())
190
204
  self._logger.debug("H5Py Cache_setting=%s (_mdc, _nslots, _nbytes, _w0)", settings)
191
205
 
192
- # Store the mode in order to allow user to differentiate harvesting vs emulation data
193
- if isinstance(self._mode, str) and self._mode in self.mode_dtype_dict:
194
- self.h5file.attrs["mode"] = self._mode
195
-
196
- if (
197
- isinstance(self._datatype, EnergyDType)
198
- and self._datatype in self.mode_dtype_dict[self.get_mode()]
199
- ):
200
- self.h5file["data"].attrs["datatype"] = self._datatype.name
201
- elif not self._modify:
202
- self._logger.error("datatype invalid? '%s' not written", self._datatype)
203
-
204
- if isinstance(self._window_samples, int):
205
- self.h5file["data"].attrs["window_samples"] = self._window_samples
206
- if datatype == EnergyDType.ivcurve and (self._window_samples in {None, 0}):
207
- raise ValueError("Window Size argument needed for ivcurve-Datatype")
208
-
209
- # include cal-data
210
- for ds, param in product(["current", "voltage", "time"], ["gain", "offset"]):
211
- self.h5file["data"][ds].attrs[param] = self._cal[ds][param]
212
-
213
206
  super().__init__(file_path=None, verbose=verbose)
214
207
 
215
208
  def __enter__(self) -> Self:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: shepherd_core
3
- Version: 2024.9.1
3
+ Version: 2024.11.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>
@@ -3,8 +3,8 @@ shepherd_core/calibration_hw_def.py,sha256=_nMzgNzSnYyqcLnVCGd4tfA2e0avUXbccjmNp
3
3
  shepherd_core/commons.py,sha256=vymKXWcy_1bz7ChzzEATUkJ4p3czCzjIdsSehVjJOY8,218
4
4
  shepherd_core/logger.py,sha256=4Q4hTI-nccOZ1_A68fo4UEctfu3pJx3IeHfa9VuDDEo,1804
5
5
  shepherd_core/reader.py,sha256=Sg7s5UfV01CejI3_nolG7qrSDUBenmt1WPo2BPJee8o,27058
6
- shepherd_core/version.py,sha256=27CgGjJQqgAy26osZGWijS3x6BU9n5GVv3D0T_smBy4,75
7
- shepherd_core/writer.py,sha256=t53fXkYUWHhYnOFnHCoMWwUADkgYydy9Dg66PiqPa68,14946
6
+ shepherd_core/version.py,sha256=_cAEEjp9MalkLrnbibrPNp6zEr3U5KIC-gmZvPG5QqA,76
7
+ shepherd_core/writer.py,sha256=GMR-7vkOgpTNPoknBWsRsC7-b7iGMtT60-KtSKunNe8,14636
8
8
  shepherd_core/data_models/__init__.py,sha256=IVjKbT2Ilz5bev325EvAuuhd9LfQgQ1u7qKo6dhVA2k,1866
9
9
  shepherd_core/data_models/readme.md,sha256=1bdfEypY_0NMhXLxOPRnLAsFca0HuHdq7_01yEWxvUs,2470
10
10
  shepherd_core/data_models/virtual_source_doc.txt,sha256=KizMcfGKj7BnHIbaJHT7KeTF01SV__UXv01qV_DGHSs,6057
@@ -24,7 +24,7 @@ shepherd_core/data_models/content/firmware_datatype.py,sha256=XPU9LOoT3h5qFOlE8W
24
24
  shepherd_core/data_models/content/virtual_harvester.py,sha256=MXmSJ_nRp1mSzxfTNk60o9h5Yrp2lFMbLphUVSnNeNc,9999
25
25
  shepherd_core/data_models/content/virtual_harvester_fixture.yaml,sha256=LZe5ue1xYhXZwB3a32sva-L4uKhkQA5AtG9JzW4B2hQ,4564
26
26
  shepherd_core/data_models/content/virtual_source.py,sha256=PPAphxEXvgMM7OVZ2dBkYAvJQkmj5Kb2BYFogVUs7B8,15354
27
- shepherd_core/data_models/content/virtual_source_fixture.yaml,sha256=wdHwuTf8-EhuSLnCQA5Ay68aiyKtXBEtJqfSc4v0sKg,11136
27
+ shepherd_core/data_models/content/virtual_source_fixture.yaml,sha256=1o-31mGgn7eyCNidKoOUp9vZh3K4Al0kJgmz54Q2DAE,11191
28
28
  shepherd_core/data_models/experiment/__init__.py,sha256=9TE9_aSnCNRhagsIWLTE8XkyjyMGB7kEGdswl-296v0,645
29
29
  shepherd_core/data_models/experiment/experiment.py,sha256=wnn6T3czuh4rz6OSYtMltCTbRpPX55TLVAtQcKO7Uhg,4044
30
30
  shepherd_core/data_models/experiment/observer_features.py,sha256=qxnb7anuQz9ZW5IUlPdUXYPIl5U7O9uXkJqZtMnAb0Y,5156
@@ -67,14 +67,14 @@ shepherd_core/testbed_client/client_web.py,sha256=iMh5T91152uugbFsqr2vvxLser0KIo
67
67
  shepherd_core/testbed_client/fixtures.py,sha256=4Uk583R4r6I5IB78HxOn-9UNH3sbFha7OPEdcSXvMCU,9939
68
68
  shepherd_core/testbed_client/user_model.py,sha256=5M3vWkAGBwdGDUYAanAjrZwpzMBlh3XLOVvNYWiLmms,2107
69
69
  shepherd_core/vsource/__init__.py,sha256=GVB-FwuO2mvM15mGX9EQC1lbUmHMLmUEFGYkGmIngPM,771
70
- shepherd_core/vsource/target_model.py,sha256=xix2VqH9PeVbMG0Pq7jpwrnD1dEbCASb3x0Llgmqge8,5055
71
- shepherd_core/vsource/virtual_converter_model.py,sha256=Mhm0iss8CD8Xcg6fsmtSp5w3Jc1zzV6RxOVOQC-tXto,11405
72
- shepherd_core/vsource/virtual_harvester_model.py,sha256=_Qq5F_0AeqkMHKcLvWQWne6ENsmygFgoSi-IXebRKAA,9689
70
+ shepherd_core/vsource/target_model.py,sha256=LaB5ppi2-IIpIepDqDvOliR-BupzccJl44yRxjlF-ms,5113
71
+ shepherd_core/vsource/virtual_converter_model.py,sha256=3TyxphUMunoGhMda7AWCHZQU8pjRSvxB-9R8lfZFnok,11592
72
+ shepherd_core/vsource/virtual_harvester_model.py,sha256=GyA0uGl3r42t5c4roYtEaj22b0-b5DAHUr2e9DuNn-c,9765
73
73
  shepherd_core/vsource/virtual_harvester_simulation.py,sha256=EiBrvmc6D2N7Z0DqFBWPdRJK6hR8Q3iQaj7EYP9pLA0,2405
74
74
  shepherd_core/vsource/virtual_source_model.py,sha256=-JSYUfsnYlNo5RfPBhx2G33fo5AjSeFSf2O6unroyFw,2945
75
75
  shepherd_core/vsource/virtual_source_simulation.py,sha256=k1v2zpNdJTqiO9uY8TXaq-IUKK6m5l-LEWebYva0skk,5088
76
- shepherd_core-2024.9.1.dist-info/METADATA,sha256=LlCH9yhqfIQRRZnSscGSeEad4xPaqCWw53zRi2kgF9s,7817
77
- shepherd_core-2024.9.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
78
- shepherd_core-2024.9.1.dist-info/top_level.txt,sha256=wy-t7HRBrKARZxa-Y8_j8d49oVHnulh-95K9ikxVhew,14
79
- shepherd_core-2024.9.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
80
- shepherd_core-2024.9.1.dist-info/RECORD,,
76
+ shepherd_core-2024.11.1.dist-info/METADATA,sha256=TPLadz0PyPjY4RxradpDtestEq_6U2ILu9tVNIIG7q0,7818
77
+ shepherd_core-2024.11.1.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
78
+ shepherd_core-2024.11.1.dist-info/top_level.txt,sha256=wy-t7HRBrKARZxa-Y8_j8d49oVHnulh-95K9ikxVhew,14
79
+ shepherd_core-2024.11.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
80
+ shepherd_core-2024.11.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (74.1.2)
2
+ Generator: setuptools (75.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5