Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Frequenz Python SDK Release Notes

## Bug fixes
## Summary

- `FormulaEngine` and `FormulaEngine3Phase` are now type aliases to `Formula` and `Formula3Phase`, fixing a typing issue introduced in `v1.0.0-rc2202`.
<!-- Here goes a general summary of what this release is about -->

## Upgrading

<!-- Here goes notes on how to upgrade from previous versions, including deprecations and what they should be replaced with -->

## New Features

<!-- Here goes the main new features and examples or instructions on how to use them -->

## Bug Fixes

- Fixed an off-by-one calculation in `OrderedRingBuffer.count_covered` by switching to integer timedelta division, ensuring accurate sample counting for all window sizes and sampling periods.
3 changes: 1 addition & 2 deletions benchmarks/timeseries/periodic_feature_extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ def _calculate_avg_window(
reshaped = feature_extractor._reshape_np_array( # pylint: disable=protected-access
window, window_size
)
# ignoring the type because np.average returns Any
return np.average(reshaped[:, :window_size], axis=0) # type: ignore[no-any-return]
return np.average(reshaped[:, :window_size], axis=0)


def _calculate_avg_window_py(
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ dependencies = [
# changing the version
# (plugins.mkdocstrings.handlers.python.import)
"frequenz-client-microgrid >= 0.18.1, < 0.19.0",
"frequenz-microgrid-component-graph >= 0.3.2, < 0.4",
"frequenz-microgrid-component-graph >= 0.3.2, < 0.3.4",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have not be committed 😭

We are finally not going this route. I made a follow-up PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry 😬

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries and keep the contributions coming!

"frequenz-client-common >= 0.3.6, < 0.4.0",
"frequenz-channels >= 1.6.1, < 2.0.0",
"frequenz-quantities[marshmallow] >= 1.0.0, < 2.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,4 @@ def avg(
The averaged timeseries window.
"""
(reshaped, window_size) = self._get_reshaped_np_array(start, end)
return np.average( # type: ignore[no-any-return]
reshaped[:, :window_size], axis=0, weights=weights
)
return np.average(reshaped[:, :window_size], axis=0, weights=weights)
5 changes: 1 addition & 4 deletions src/frequenz/sdk/timeseries/_ringbuffer/buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -705,10 +705,7 @@ def count_covered(
The count of samples between the oldest and newest (inclusive) valid samples
or 0 if there are is no time range covered.
"""
return int(
self._covered_time_range(since, until).total_seconds()
// self._sampling_period.total_seconds()
)
return self._covered_time_range(since, until) // self._sampling_period

def count_valid(
self, *, since: datetime | None = None, until: datetime | None = None
Expand Down
27 changes: 27 additions & 0 deletions tests/timeseries/test_moving_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,33 @@ async def test_resampling_window(fake_time: time_machine.Coordinates) -> None:
assert 4.9 < value < 5.1


async def test_moving_window_length(fake_time: time_machine.Coordinates) -> None:
"""Test moving window length without resampling."""
channel = Broadcast[Sample[Quantity]](name="net_power")
sender = channel.new_sender()

window_size = timedelta(seconds=1)
input_sampling = timedelta(seconds=0.1)

async with MovingWindow(
size=window_size,
resampled_data_recv=channel.new_receiver(),
input_sampling_period=input_sampling,
) as window:
assert window.capacity == window_size / input_sampling, "Wrong window capacity"
assert window.count_valid() == 0, "Window should be empty at the beginning"
stream_values = [4.0, 8.0, 2.0, 6.0, 5.0] * 100
for value in stream_values:
timestamp = datetime.now(tz=timezone.utc)
sample = Sample(timestamp, Quantity(float(value)))
await sender.send(sample)
await asyncio.sleep(0.1)
fake_time.shift(0.1)
assert window.count_valid() <= window.count_covered()

assert window.count_valid() == window_size / input_sampling


async def test_timestamps() -> None:
"""Test indexing a window by timestamp."""
window, sender = init_moving_window(timedelta(seconds=5))
Expand Down