shepherd-core 2023.12.1__py3-none-any.whl → 2024.4.2__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_core/__init__.py +5 -4
- shepherd_core/calibration_hw_def.py +9 -1
- shepherd_core/commons.py +2 -0
- shepherd_core/data_models/__init__.py +11 -0
- shepherd_core/data_models/base/__init__.py +4 -1
- shepherd_core/data_models/base/cal_measurement.py +18 -6
- shepherd_core/data_models/base/calibration.py +41 -16
- shepherd_core/data_models/base/content.py +20 -5
- shepherd_core/data_models/base/shepherd.py +23 -12
- shepherd_core/data_models/base/timezone.py +5 -0
- shepherd_core/data_models/base/wrapper.py +3 -3
- shepherd_core/data_models/content/__init__.py +5 -4
- shepherd_core/data_models/content/_external_fixtures.yaml +32 -16
- shepherd_core/data_models/content/energy_environment.py +7 -5
- shepherd_core/data_models/content/energy_environment_fixture.yaml +3 -0
- shepherd_core/data_models/content/firmware.py +12 -5
- shepherd_core/data_models/content/firmware_datatype.py +7 -0
- shepherd_core/data_models/content/virtual_harvester.py +25 -20
- shepherd_core/data_models/content/virtual_harvester_fixture.yaml +1 -0
- shepherd_core/data_models/content/virtual_source.py +40 -23
- shepherd_core/data_models/content/virtual_source_fixture.yaml +1 -0
- shepherd_core/data_models/experiment/__init__.py +5 -4
- shepherd_core/data_models/experiment/experiment.py +16 -15
- shepherd_core/data_models/experiment/observer_features.py +18 -12
- shepherd_core/data_models/experiment/target_config.py +11 -7
- shepherd_core/data_models/readme.md +88 -0
- shepherd_core/data_models/task/__init__.py +10 -3
- shepherd_core/data_models/task/emulation.py +9 -6
- shepherd_core/data_models/task/firmware_mod.py +4 -2
- shepherd_core/data_models/task/harvest.py +5 -4
- shepherd_core/data_models/task/observer_tasks.py +4 -2
- shepherd_core/data_models/task/programming.py +3 -1
- shepherd_core/data_models/task/testbed_tasks.py +10 -4
- shepherd_core/data_models/testbed/__init__.py +5 -2
- shepherd_core/data_models/testbed/cape.py +8 -6
- shepherd_core/data_models/testbed/gpio.py +11 -9
- shepherd_core/data_models/testbed/mcu.py +10 -10
- shepherd_core/data_models/testbed/observer.py +10 -5
- shepherd_core/data_models/testbed/observer_fixture.yaml +23 -22
- shepherd_core/data_models/testbed/target.py +5 -3
- shepherd_core/data_models/testbed/target_fixture.yaml +11 -11
- shepherd_core/data_models/testbed/testbed.py +6 -3
- shepherd_core/decoder_waveform/__init__.py +2 -0
- shepherd_core/decoder_waveform/uart.py +44 -25
- shepherd_core/fw_tools/__init__.py +2 -0
- shepherd_core/fw_tools/converter.py +20 -9
- shepherd_core/fw_tools/converter_elf.py +3 -0
- shepherd_core/fw_tools/patcher.py +16 -4
- shepherd_core/fw_tools/validation.py +25 -5
- shepherd_core/inventory/__init__.py +66 -6
- shepherd_core/inventory/python.py +4 -0
- shepherd_core/inventory/system.py +13 -1
- shepherd_core/inventory/target.py +4 -0
- shepherd_core/logger.py +5 -0
- shepherd_core/reader.py +44 -26
- shepherd_core/testbed_client/__init__.py +2 -0
- shepherd_core/testbed_client/cache_path.py +17 -0
- shepherd_core/testbed_client/client.py +14 -8
- shepherd_core/testbed_client/fixtures.py +30 -11
- shepherd_core/testbed_client/user_model.py +13 -6
- shepherd_core/vsource/__init__.py +2 -0
- shepherd_core/vsource/virtual_converter_model.py +11 -4
- shepherd_core/vsource/virtual_harvester_model.py +8 -1
- shepherd_core/vsource/virtual_source_model.py +10 -5
- shepherd_core/writer.py +28 -20
- {shepherd_core-2023.12.1.dist-info → shepherd_core-2024.4.2.dist-info}/METADATA +50 -34
- shepherd_core-2024.4.2.dist-info/RECORD +75 -0
- {shepherd_core-2023.12.1.dist-info → shepherd_core-2024.4.2.dist-info}/WHEEL +1 -1
- {shepherd_core-2023.12.1.dist-info → shepherd_core-2024.4.2.dist-info}/top_level.txt +0 -1
- shepherd_core-2023.12.1.dist-info/RECORD +0 -117
- tests/__init__.py +0 -0
- tests/conftest.py +0 -64
- tests/data_models/__init__.py +0 -0
- tests/data_models/conftest.py +0 -14
- tests/data_models/example_cal_data.yaml +0 -31
- tests/data_models/example_cal_data_faulty.yaml +0 -29
- tests/data_models/example_cal_meas.yaml +0 -178
- tests/data_models/example_cal_meas_faulty1.yaml +0 -142
- tests/data_models/example_cal_meas_faulty2.yaml +0 -136
- tests/data_models/example_config_emulator.yaml +0 -41
- tests/data_models/example_config_experiment.yaml +0 -16
- tests/data_models/example_config_experiment_alternative.yaml +0 -14
- tests/data_models/example_config_harvester.yaml +0 -15
- tests/data_models/example_config_testbed.yaml +0 -26
- tests/data_models/example_config_virtsource.yaml +0 -78
- tests/data_models/test_base_models.py +0 -205
- tests/data_models/test_content_fixtures.py +0 -41
- tests/data_models/test_content_models.py +0 -282
- tests/data_models/test_examples.py +0 -48
- tests/data_models/test_experiment_models.py +0 -277
- tests/data_models/test_task_generation.py +0 -52
- tests/data_models/test_task_models.py +0 -131
- tests/data_models/test_testbed_fixtures.py +0 -47
- tests/data_models/test_testbed_models.py +0 -187
- tests/decoder_waveform/__init__.py +0 -0
- tests/decoder_waveform/test_decoder.py +0 -34
- tests/fw_tools/__init__.py +0 -0
- tests/fw_tools/conftest.py +0 -5
- tests/fw_tools/test_converter.py +0 -76
- tests/fw_tools/test_patcher.py +0 -66
- tests/fw_tools/test_validation.py +0 -56
- tests/inventory/__init__.py +0 -0
- tests/inventory/test_inventory.py +0 -20
- tests/test_cal_hw.py +0 -34
- tests/test_examples.py +0 -40
- tests/test_logger.py +0 -15
- tests/test_reader.py +0 -283
- tests/test_writer.py +0 -169
- tests/testbed_client/__init__.py +0 -0
- tests/vsource/__init__.py +0 -0
- tests/vsource/conftest.py +0 -49
- tests/vsource/test_converter.py +0 -161
- tests/vsource/test_harvester.py +0 -73
- tests/vsource/test_z.py +0 -5
- /shepherd_core/data_models/{doc_virtual_source.py → virtual_source_doc.txt} +0 -0
- {shepherd_core-2023.12.1.dist-info → shepherd_core-2024.4.2.dist-info}/zip-safe +0 -0
tests/test_examples.py
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import subprocess
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
import pytest
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
@pytest.fixture
|
|
9
|
-
def example_path() -> Path:
|
|
10
|
-
path = Path(__file__).resolve().parent.parent / "examples"
|
|
11
|
-
os.chdir(path)
|
|
12
|
-
return path
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
examples = [
|
|
16
|
-
"experiment_generic_var1.py",
|
|
17
|
-
"experiment_models.py",
|
|
18
|
-
"inventory.py",
|
|
19
|
-
"uart_decode_waveform.py",
|
|
20
|
-
"vharvester_simulation.py",
|
|
21
|
-
"vsource_simulation.py",
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@pytest.mark.parametrize("file", examples)
|
|
26
|
-
def test_example_scripts(example_path: Path, file: str) -> None:
|
|
27
|
-
subprocess.check_call(f"python {example_path / file}", shell=True)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
examples_fw = [
|
|
31
|
-
"firmware_model.py",
|
|
32
|
-
"firmware_modification.py",
|
|
33
|
-
]
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
@pytest.mark.converter
|
|
37
|
-
@pytest.mark.elf
|
|
38
|
-
@pytest.mark.parametrize("file", examples_fw)
|
|
39
|
-
def test_example_scripts_fw(example_path: Path, file: str) -> None:
|
|
40
|
-
subprocess.check_call(f"python {example_path / file}", shell=True)
|
tests/test_logger.py
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
|
|
3
|
-
from shepherd_core import get_verbose_level
|
|
4
|
-
from shepherd_core import increase_verbose_level
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@pytest.mark.parametrize("log_level", range(-5, 10))
|
|
8
|
-
def test_log_levels(log_level: int) -> None:
|
|
9
|
-
increase_verbose_level(log_level)
|
|
10
|
-
if log_level <= 2:
|
|
11
|
-
assert get_verbose_level() == 2
|
|
12
|
-
elif log_level <= 3:
|
|
13
|
-
assert get_verbose_level() == log_level
|
|
14
|
-
else:
|
|
15
|
-
assert get_verbose_level() == 3
|
tests/test_reader.py
DELETED
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
|
|
4
|
-
import h5py
|
|
5
|
-
import pytest
|
|
6
|
-
import yaml
|
|
7
|
-
|
|
8
|
-
from shepherd_core import Reader
|
|
9
|
-
from shepherd_core import Writer
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def test_reader_metadata(data_h5: Path) -> None:
|
|
13
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
14
|
-
assert sfr.energy() > 0
|
|
15
|
-
assert sfr.is_valid()
|
|
16
|
-
|
|
17
|
-
meta_data_a = sfr.save_metadata()
|
|
18
|
-
meta_path = data_h5.resolve().with_suffix(".yaml")
|
|
19
|
-
assert meta_path.exists()
|
|
20
|
-
with meta_path.open() as meta_file:
|
|
21
|
-
meta_data_b = yaml.safe_load(meta_file)
|
|
22
|
-
assert len(meta_data_b) == len(meta_data_a)
|
|
23
|
-
assert sys.getsizeof(meta_data_b) == sys.getsizeof(meta_data_a)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def test_reader_items(data_h5: Path) -> None:
|
|
27
|
-
"""Access internal"""
|
|
28
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
29
|
-
_ = sfr["data"] # group
|
|
30
|
-
_ = sfr["mode"] # attribute
|
|
31
|
-
with pytest.raises(KeyError):
|
|
32
|
-
_ = sfr["non-existing"]
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def test_reader_open(tmp_path: Path) -> None:
|
|
36
|
-
with pytest.raises(TypeError):
|
|
37
|
-
Reader(file_path=None)
|
|
38
|
-
|
|
39
|
-
tmp_file = (tmp_path / "data.h5").resolve()
|
|
40
|
-
|
|
41
|
-
with pytest.raises(FileNotFoundError):
|
|
42
|
-
Reader(file_path=tmp_file)
|
|
43
|
-
|
|
44
|
-
with tmp_file.open("w") as tf:
|
|
45
|
-
tf.write("abc def ghi")
|
|
46
|
-
with pytest.raises(TypeError):
|
|
47
|
-
Reader(file_path=tmp_file)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def test_reader_meta_repr(data_h5: Path) -> None:
|
|
51
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
52
|
-
print(sfr)
|
|
53
|
-
print(sfr.get_calibration_data())
|
|
54
|
-
print(sfr.get_hrv_config())
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def test_reader_read_open_end(data_h5: Path) -> None:
|
|
58
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
59
|
-
for buf in sfr.read_buffers():
|
|
60
|
-
print(len(buf[0]))
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def test_reader_read_5(data_h5: Path) -> None:
|
|
64
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
65
|
-
for buf in sfr.read_buffers(end_n=5):
|
|
66
|
-
print(len(buf[0]))
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def test_reader_read_start_late(data_h5: Path) -> None:
|
|
70
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
71
|
-
for buf in sfr.read_buffers(start_n=2):
|
|
72
|
-
print(len(buf[0]))
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
def test_reader_read_raw(data_h5: Path) -> None:
|
|
76
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
77
|
-
for buf in sfr.read_buffers(is_raw=True):
|
|
78
|
-
print(len(buf[0]))
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def test_reader_non_valid(tmp_path: Path) -> None:
|
|
82
|
-
data_h5 = tmp_path / "data.h5"
|
|
83
|
-
with h5py.File(data_h5, "w") as h5f:
|
|
84
|
-
grp_data = h5f.create_group("data")
|
|
85
|
-
grp_data.create_dataset("time", (0,))
|
|
86
|
-
grp_data.create_dataset("current", (0,))
|
|
87
|
-
grp_data.create_dataset("voltage", (0,))
|
|
88
|
-
grp_data["time"].attrs["gain"] = 1
|
|
89
|
-
grp_data["current"].attrs["gain"] = 1
|
|
90
|
-
grp_data["voltage"].attrs["gain"] = 1
|
|
91
|
-
grp_data["time"].attrs["offset"] = 0
|
|
92
|
-
grp_data["current"].attrs["offset"] = 0
|
|
93
|
-
grp_data["voltage"].attrs["offset"] = 0
|
|
94
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
95
|
-
# try getting metadata -> no exception but safe defaults
|
|
96
|
-
sfr.get_window_samples()
|
|
97
|
-
sfr.get_mode()
|
|
98
|
-
sfr.get_mode()
|
|
99
|
-
sfr.get_hostname()
|
|
100
|
-
sfr.get_datatype()
|
|
101
|
-
assert not sfr.is_valid()
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def test_reader_fault_path(tmp_path: Path) -> None:
|
|
105
|
-
with pytest.raises(FileNotFoundError):
|
|
106
|
-
Reader(tmp_path, verbose=True)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def test_reader_fault_no_data(data_h5: Path) -> None:
|
|
110
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
111
|
-
del sfw.h5file["data"]
|
|
112
|
-
with pytest.raises(KeyError):
|
|
113
|
-
Reader(data_h5, verbose=True)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def test_reader_fault_no_mode(data_h5: Path) -> None:
|
|
117
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
118
|
-
del sfw.h5file.attrs["mode"]
|
|
119
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
120
|
-
assert not sfr.is_valid()
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def test_reader_fault_fake_mode(data_h5: Path) -> None:
|
|
124
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
125
|
-
sfw.h5file.attrs["mode"] = "burning"
|
|
126
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
127
|
-
assert not sfr.is_valid()
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def test_reader_fault_no_window_samples(data_h5: Path) -> None:
|
|
131
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
132
|
-
del sfw.h5file["data"].attrs["window_samples"]
|
|
133
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
134
|
-
assert not sfr.is_valid()
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
def test_reader_fault_no_datatype(data_h5: Path) -> None:
|
|
138
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
139
|
-
del sfw.h5file["data"].attrs["datatype"]
|
|
140
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
141
|
-
assert not sfr.is_valid()
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def test_reader_fault_wrong_datatype(data_h5: Path) -> None:
|
|
145
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
146
|
-
sfw.h5file["data"].attrs["datatype"] = "apples"
|
|
147
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
148
|
-
assert not sfr.is_valid()
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
def test_reader_fault_wrong_window1(data_h5: Path) -> None:
|
|
152
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
153
|
-
sfw["data"].attrs["datatype"] = "ivcurve"
|
|
154
|
-
sfw["data"].attrs["window_samples"] = 0
|
|
155
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
156
|
-
assert not sfr.is_valid()
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
def test_reader_fault_wrong_window2(data_h5: Path) -> None:
|
|
160
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
161
|
-
sfw["data"].attrs["datatype"] = "ivsample"
|
|
162
|
-
sfw["data"].attrs["window_samples"] = 1111
|
|
163
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
164
|
-
# only triggers warning
|
|
165
|
-
assert sfr.is_valid()
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
def test_reader_fault_no_current(data_h5: Path) -> None:
|
|
169
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
170
|
-
del sfw.h5file["data"]["current"]
|
|
171
|
-
with pytest.raises(KeyError):
|
|
172
|
-
Reader(data_h5, verbose=True)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
def test_reader_fault_no_voltage(data_h5: Path) -> None:
|
|
176
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
177
|
-
del sfw.h5file["data"]["voltage"]
|
|
178
|
-
with pytest.raises(KeyError):
|
|
179
|
-
Reader(data_h5, verbose=True)
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
def test_reader_fault_no_gain(data_h5: Path) -> None:
|
|
183
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
184
|
-
del sfw.h5file["data"]["time"].attrs["gain"]
|
|
185
|
-
with pytest.raises(KeyError):
|
|
186
|
-
Reader(data_h5, verbose=True)
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
def test_reader_fault_no_offset(data_h5: Path) -> None:
|
|
190
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
191
|
-
del sfw.h5file["data"]["time"].attrs["offset"]
|
|
192
|
-
with pytest.raises(KeyError):
|
|
193
|
-
Reader(data_h5, verbose=True)
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
def test_reader_fault_non_eq_time(data_h5: Path) -> None:
|
|
197
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
198
|
-
sfw.h5file["data"]["time"].resize((0,))
|
|
199
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
200
|
-
assert sfr.is_valid()
|
|
201
|
-
# soft-criteria ... reader just complains
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
def test_reader_fault_unaligned(data_h5: Path) -> None:
|
|
205
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
206
|
-
new_size = sfw.samples_per_buffer / 2
|
|
207
|
-
sfw.h5file["data"]["time"].resize((new_size,))
|
|
208
|
-
sfw.h5file["data"]["voltage"].resize((new_size,))
|
|
209
|
-
sfw.h5file["data"]["current"].resize((new_size,))
|
|
210
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
211
|
-
assert sfr.is_valid()
|
|
212
|
-
# soft-criteria ... reader just complains
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
def test_reader_fault_strange_compression(data_h5: Path) -> None:
|
|
216
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
217
|
-
time = sfw.h5file["data"]["time"][:]
|
|
218
|
-
del sfw.h5file["data"]["time"]
|
|
219
|
-
sfw.h5file["data"].create_dataset(
|
|
220
|
-
"time",
|
|
221
|
-
(0,),
|
|
222
|
-
dtype="u8",
|
|
223
|
-
maxshape=(None,),
|
|
224
|
-
compression="lzf", # something like szip wanted
|
|
225
|
-
)
|
|
226
|
-
sfw.h5file["data"]["time"].resize(time.shape)
|
|
227
|
-
sfw.h5file["data"]["time"][0 : time.shape[0]] = time[: time.shape[0]]
|
|
228
|
-
sfw.h5file["data"]["time"].attrs["gain"] = 1
|
|
229
|
-
sfw.h5file["data"]["time"].attrs["offset"] = 0
|
|
230
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
231
|
-
assert sfr.is_valid()
|
|
232
|
-
# soft-criteria ... reader just complains
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
def test_reader_fault_slow_compression(data_h5: Path) -> None:
|
|
236
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
237
|
-
time = sfw.h5file["data"]["time"][:]
|
|
238
|
-
del sfw.h5file["data"]["time"]
|
|
239
|
-
sfw.h5file["data"].create_dataset(
|
|
240
|
-
"time",
|
|
241
|
-
(0,),
|
|
242
|
-
dtype="u8",
|
|
243
|
-
maxshape=(None,),
|
|
244
|
-
compression="gzip",
|
|
245
|
-
compression_opts=9,
|
|
246
|
-
)
|
|
247
|
-
sfw.h5file["data"]["time"].resize(time.shape)
|
|
248
|
-
sfw.h5file["data"]["time"][0 : time.shape[0]] = time[: time.shape[0]]
|
|
249
|
-
sfw.h5file["data"]["time"].attrs["gain"] = 1
|
|
250
|
-
sfw.h5file["data"]["time"].attrs["offset"] = 0
|
|
251
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
252
|
-
assert sfr.is_valid()
|
|
253
|
-
# soft-criteria ... reader just complains
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
def test_reader_fault_no_hostname(data_h5: Path) -> None:
|
|
257
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
258
|
-
sfw.h5file.attrs["hostname"] = "unknown"
|
|
259
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
260
|
-
assert sfr.is_valid()
|
|
261
|
-
# soft-criteria ... reader just complains
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
def test_reader_fault_jumps_timestamp(data_h5: Path) -> None:
|
|
265
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
266
|
-
assert sfr.check_timediffs()
|
|
267
|
-
with Writer(data_h5, modify_existing=True) as sfw:
|
|
268
|
-
sfw.h5file["data"]["time"][sfw.samples_per_buffer] = 0
|
|
269
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
270
|
-
assert not sfr.check_timediffs()
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
def test_reader_save_meta(data_h5: Path) -> None:
|
|
274
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
275
|
-
assert sfr.save_metadata() != {}
|
|
276
|
-
# yaml now already exists
|
|
277
|
-
assert sfr.save_metadata() == {}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
def test_reader_save_meta_fail(data_h5: Path) -> None:
|
|
281
|
-
with Reader(data_h5, verbose=True) as sfr:
|
|
282
|
-
sfr.file_path = None
|
|
283
|
-
assert sfr.save_metadata() == {}
|
tests/test_writer.py
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
from typing import Optional
|
|
3
|
-
from typing import Union
|
|
4
|
-
|
|
5
|
-
import numpy as np
|
|
6
|
-
import pytest
|
|
7
|
-
|
|
8
|
-
from shepherd_core import Reader
|
|
9
|
-
from shepherd_core import Writer
|
|
10
|
-
from shepherd_core.data_models import CalibrationEmulator as CalEmu
|
|
11
|
-
from shepherd_core.data_models import CalibrationHarvester as CalHrv
|
|
12
|
-
from shepherd_core.data_models import CalibrationSeries as CalSeries
|
|
13
|
-
from shepherd_core.data_models.task import Compression
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def generate_shp_file(
|
|
17
|
-
store_path: Path,
|
|
18
|
-
mode: Optional[str] = None,
|
|
19
|
-
datatype: Optional[str] = None,
|
|
20
|
-
window_samples: Optional[int] = None,
|
|
21
|
-
cal_data: Union[CalSeries, CalEmu, CalHrv, None] = None,
|
|
22
|
-
config: Optional[dict] = None,
|
|
23
|
-
compression: Optional[Compression] = Compression.default,
|
|
24
|
-
hostname: str = "unknown",
|
|
25
|
-
) -> Path:
|
|
26
|
-
if config is None:
|
|
27
|
-
config = {}
|
|
28
|
-
with Writer(
|
|
29
|
-
store_path,
|
|
30
|
-
mode=mode,
|
|
31
|
-
datatype=datatype,
|
|
32
|
-
window_samples=window_samples,
|
|
33
|
-
cal_data=cal_data,
|
|
34
|
-
compression=compression,
|
|
35
|
-
verbose=True,
|
|
36
|
-
) as file:
|
|
37
|
-
file.store_hostname(hostname)
|
|
38
|
-
file.store_config(config)
|
|
39
|
-
duration_s = 2
|
|
40
|
-
timestamps = np.arange(0.0, duration_s, file.sample_interval_ns / 1e9)
|
|
41
|
-
voltages = np.linspace(3.60, 1.90, int(file.samplerate_sps * duration_s))
|
|
42
|
-
currents = np.linspace(100e-6, 2000e-6, int(file.samplerate_sps * duration_s))
|
|
43
|
-
file.append_iv_data_si(timestamps, voltages, currents)
|
|
44
|
-
return store_path
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
@pytest.fixture
|
|
48
|
-
def h5_path(tmp_path: Path) -> Path:
|
|
49
|
-
return tmp_path / "hrv_test.h5"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
@pytest.fixture
|
|
53
|
-
def h5_file(h5_path: Path) -> Path:
|
|
54
|
-
generate_shp_file(h5_path)
|
|
55
|
-
return h5_path
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def test_writer_basics(h5_path: Path) -> None:
|
|
59
|
-
generate_shp_file(h5_path)
|
|
60
|
-
with Reader(h5_path, verbose=True) as file:
|
|
61
|
-
assert round(file.runtime_s) == 2
|
|
62
|
-
assert file.get_window_samples() == 0
|
|
63
|
-
assert file.get_mode() == "harvester"
|
|
64
|
-
assert file.get_config() == {}
|
|
65
|
-
assert file.get_datatype() == "ivsample"
|
|
66
|
-
assert file.get_hostname() == "unknown"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def test_writer_compression_1(h5_path: Path) -> None:
|
|
70
|
-
generate_shp_file(h5_path, compression=Compression.gzip1)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def test_writer_unique_path(h5_file: Path) -> None:
|
|
74
|
-
with Writer(h5_file) as sfw:
|
|
75
|
-
assert sfw.file_path != h5_path
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def test_writer_faulty_mode(h5_path: Path) -> None:
|
|
79
|
-
with pytest.raises(ValueError):
|
|
80
|
-
generate_shp_file(h5_path, mode="excavator", datatype="ivcurve")
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def test_writer_faulty_datatype(h5_path: Path) -> None:
|
|
84
|
-
with pytest.raises(ValueError):
|
|
85
|
-
generate_shp_file(h5_path, mode="emulator", datatype="ivcurve")
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def test_writer_faulty_path(tmp_path: Path) -> None:
|
|
89
|
-
with pytest.raises(TypeError):
|
|
90
|
-
generate_shp_file(tmp_path)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def test_writer_modify(h5_file: Path) -> None:
|
|
94
|
-
with Writer(h5_file, modify_existing=True) as sfw:
|
|
95
|
-
sfw.store_hostname("sheep")
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def test_writer_init_cal_emu(h5_path: Path) -> None:
|
|
99
|
-
generate_shp_file(h5_path, cal_data=CalEmu())
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
def test_writer_init_cal_hrv(h5_path: Path) -> None:
|
|
103
|
-
generate_shp_file(h5_path, cal_data=CalHrv())
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def test_writer_init_cal_series(h5_path: Path) -> None:
|
|
107
|
-
cs = CalSeries.from_cal(CalHrv())
|
|
108
|
-
generate_shp_file(h5_path, cal_data=cs)
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
def test_writer_faulty_window(h5_path: Path) -> None:
|
|
112
|
-
with pytest.raises(ValueError):
|
|
113
|
-
generate_shp_file(h5_path, mode="harvester", datatype="ivcurve")
|
|
114
|
-
with pytest.raises(ValueError):
|
|
115
|
-
generate_shp_file(
|
|
116
|
-
h5_path,
|
|
117
|
-
mode="harvester",
|
|
118
|
-
datatype="ivcurve",
|
|
119
|
-
window_samples=0,
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def test_writer_append_raw(h5_path: Path) -> None:
|
|
124
|
-
with Writer(h5_path) as sfw:
|
|
125
|
-
data_nd = np.zeros((sfw.samples_per_buffer,))
|
|
126
|
-
time_float = 5.5
|
|
127
|
-
time_int = 3
|
|
128
|
-
time_nd = 3 + data_nd
|
|
129
|
-
sfw.append_iv_data_raw(time_float, data_nd, data_nd)
|
|
130
|
-
sfw.append_iv_data_raw(time_int, data_nd, data_nd)
|
|
131
|
-
sfw.append_iv_data_raw(time_nd, data_nd, data_nd)
|
|
132
|
-
with pytest.raises(ValueError):
|
|
133
|
-
sfw.append_iv_data_raw(None, data_nd, data_nd)
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
def test_writer_align(h5_path: Path) -> None:
|
|
137
|
-
with Writer(h5_path) as sfw:
|
|
138
|
-
length = int(5.5 * sfw.samples_per_buffer)
|
|
139
|
-
time_nd = np.arange(0, length * sfw.sample_interval_ns, sfw.sample_interval_ns)
|
|
140
|
-
data_nd = np.zeros((int(length),))
|
|
141
|
-
sfw.append_iv_data_raw(time_nd, data_nd, data_nd)
|
|
142
|
-
with Reader(h5_path) as sfr:
|
|
143
|
-
assert sfr.ds_voltage.size < length
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
def test_writer_not_align(h5_path: Path) -> None:
|
|
147
|
-
with Writer(h5_path) as sfw:
|
|
148
|
-
length = int(5.5 * sfw.samples_per_buffer)
|
|
149
|
-
sample_interval = 10 * sfw.sample_interval_ns
|
|
150
|
-
time_nd = np.arange(0, length * sample_interval, sample_interval)
|
|
151
|
-
data_nd = np.zeros((int(length),))
|
|
152
|
-
sfw.append_iv_data_raw(time_nd, data_nd, data_nd)
|
|
153
|
-
with Reader(h5_path) as sfr:
|
|
154
|
-
assert sfr.ds_voltage.size == length
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
def test_writer_setter(h5_path: Path) -> None:
|
|
158
|
-
name = "pingu"
|
|
159
|
-
with Writer(h5_path) as sfw:
|
|
160
|
-
sfw["hostname"] = name
|
|
161
|
-
with Reader(h5_path) as sfr:
|
|
162
|
-
assert sfr.get_hostname() == name
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
# TODO:
|
|
166
|
-
# - test writing different and confirming them
|
|
167
|
-
# - different compressions and their size relative to each other
|
|
168
|
-
# - also invalid
|
|
169
|
-
# - read raw-data
|
tests/testbed_client/__init__.py
DELETED
|
File without changes
|
tests/vsource/__init__.py
DELETED
|
File without changes
|
tests/vsource/conftest.py
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
|
|
4
|
-
import pytest
|
|
5
|
-
|
|
6
|
-
from shepherd_data import ivonne
|
|
7
|
-
from shepherd_data import mppt
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@pytest.fixture
|
|
11
|
-
def file_ivonne() -> Path:
|
|
12
|
-
path = Path(__file__).resolve().parent.parent.parent.parent / "shepherd_data/examples"
|
|
13
|
-
os.chdir(path)
|
|
14
|
-
return path / "./jogging_10m.iv"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@pytest.fixture
|
|
18
|
-
def file_isc_voc(file_ivonne: Path) -> Path:
|
|
19
|
-
path = file_ivonne.parent / "jogging_10m_isc_voc.h5"
|
|
20
|
-
if not path.exists():
|
|
21
|
-
with ivonne.Reader(file_ivonne) as db:
|
|
22
|
-
db.upsample_2_isc_voc(path, duration_s=1)
|
|
23
|
-
return path
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@pytest.fixture
|
|
27
|
-
def file_ivcurve(file_ivonne: Path) -> Path:
|
|
28
|
-
path = file_ivonne.parent / "jogging_10m_ivcurve.h5"
|
|
29
|
-
if not path.exists():
|
|
30
|
-
with ivonne.Reader(file_ivonne) as db:
|
|
31
|
-
db.convert_2_ivcurves(path, duration_s=1)
|
|
32
|
-
return path
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@pytest.fixture
|
|
36
|
-
def file_ivsample(file_ivonne: Path) -> Path:
|
|
37
|
-
path = file_ivonne.parent / "jogging_10m_ivsample.h5"
|
|
38
|
-
if not path.exists():
|
|
39
|
-
with ivonne.Reader(file_ivonne) as db:
|
|
40
|
-
tr_opt = mppt.OptimalTracker()
|
|
41
|
-
db.convert_2_ivsamples(path, tracker=tr_opt, duration_s=1)
|
|
42
|
-
return path
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
@pytest.fixture
|
|
46
|
-
def file_cleanup(file_isc_voc: Path, file_ivcurve: Path, file_ivsample: Path) -> None:
|
|
47
|
-
file_isc_voc.unlink(missing_ok=True)
|
|
48
|
-
file_ivcurve.unlink(missing_ok=True)
|
|
49
|
-
file_ivsample.unlink(missing_ok=True)
|