Skip to content

Commit 01b8d9d

Browse files
Treat NaN as gap in ring buffer (#641)
Fixes #601
2 parents ae1c2a0 + c1c8828 commit 01b8d9d

File tree

3 files changed

+79
-2
lines changed

3 files changed

+79
-2
lines changed

RELEASE_NOTES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
- A new class `Fuse` has been added to represent fuses. This class has a member variable `max_current` which represents the maximum current that can course through the fuse. If the current flowing through a fuse is greater than this limit, then the fuse will break the circuit.
2424

25+
- NaN values are treated as missing when gaps are determined in the `OrderedRingBuffer`.
2526

2627
## Bug Fixes
2728

src/frequenz/sdk/timeseries/_ringbuffer/buffer.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,17 @@ def gaps(self) -> List[Gap]:
108108
"""
109109
return self._gaps
110110

111+
def has_value(self, sample: Sample[QuantityT]) -> bool:
112+
"""Check if a sample has a value and it's not NaN.
113+
114+
Args:
115+
sample: sample to check.
116+
117+
Returns:
118+
True if the sample has a value and it's not NaN.
119+
"""
120+
return not (sample.value is None or sample.value.isnan())
121+
111122
@property
112123
def maxlen(self) -> int:
113124
"""Get the max length.
@@ -154,10 +165,14 @@ def update(self, sample: Sample[QuantityT]) -> None:
154165
)
155166

156167
# Update data
157-
value: float = np.nan if sample.value is None else sample.value.base_value
168+
if self.has_value(sample):
169+
assert sample.value is not None
170+
value = sample.value.base_value
171+
else:
172+
value = np.nan
158173
self._buffer[self.datetime_to_index(timestamp)] = value
159174

160-
self._update_gaps(timestamp, prev_newest, sample.value is None)
175+
self._update_gaps(timestamp, prev_newest, not self.has_value(sample))
161176

162177
@property
163178
def time_bound_oldest(self) -> datetime:

tests/timeseries/test_ringbuffer.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,67 @@ def test_timestamp_ringbuffer_missing_parameter(
192192
assert len(buffer.gaps) == 1
193193

194194

195+
def dt(i: int) -> datetime: # pylint: disable=invalid-name
196+
"""Create datetime objects from indices.
197+
198+
Args:
199+
i: Index to create datetime from.
200+
201+
Returns:
202+
Datetime object.
203+
"""
204+
return datetime.fromtimestamp(i, tz=timezone.utc)
205+
206+
207+
def test_gaps() -> None:
208+
"""Test gap treatment in ordered ring buffer."""
209+
buffer = OrderedRingBuffer([0.0] * 5, ONE_SECOND)
210+
assert len(buffer) == 0
211+
assert len(buffer.gaps) == 0
212+
213+
buffer.update(Sample(dt(0), Quantity(0)))
214+
assert len(buffer) == 1
215+
assert len(buffer.gaps) == 1
216+
217+
buffer.update(Sample(dt(6), Quantity(0)))
218+
assert len(buffer) == 1
219+
assert len(buffer.gaps) == 1
220+
221+
buffer.update(Sample(dt(2), Quantity(2)))
222+
buffer.update(Sample(dt(3), Quantity(3)))
223+
buffer.update(Sample(dt(4), Quantity(4)))
224+
assert len(buffer) == 4
225+
assert len(buffer.gaps) == 1
226+
227+
buffer.update(Sample(dt(3), None))
228+
assert len(buffer) == 3
229+
assert len(buffer.gaps) == 2
230+
231+
buffer.update(Sample(dt(3), Quantity(np.nan)))
232+
assert len(buffer) == 3
233+
assert len(buffer.gaps) == 2
234+
235+
buffer.update(Sample(dt(2), Quantity(np.nan)))
236+
assert len(buffer) == 2
237+
assert len(buffer.gaps) == 2
238+
239+
buffer.update(Sample(dt(3), Quantity(3)))
240+
assert len(buffer) == 3
241+
assert len(buffer.gaps) == 2
242+
243+
buffer.update(Sample(dt(2), Quantity(2)))
244+
assert len(buffer) == 4
245+
assert len(buffer.gaps) == 1
246+
247+
buffer.update(Sample(dt(5), Quantity(5)))
248+
assert len(buffer) == 5
249+
assert len(buffer.gaps) == 0
250+
251+
buffer.update(Sample(dt(99), None))
252+
assert len(buffer) == 4 # bug: should be 0 (whole range gap)
253+
assert len(buffer.gaps) == 1
254+
255+
195256
@pytest.mark.parametrize(
196257
"buffer",
197258
[

0 commit comments

Comments
 (0)