Skip to content

Commit 3842d77

Browse files
authored
Unpin mkdocs-autorefs and fix multple URLs for warnings (#1051)
This PR unpins the `mkdocs-autorefs` plugin, so we can use the latest version, but to do that we need to make some changes to the way we link to sections in the docs. The new version produces warnings when there are more than one possible URL to resolve an "autoref" link, and since we have strict more enabled, the docs fail to build if we have any warnings. The simplest way to avoid the warning in some cases is just adding the following options: ``` show_root_heading: false show_root_toc_entry: false ``` This avoids anchors being created in the user guide, so it removes the ambiguity of the link. To remove some other warnings we add a new `autorefs` plugin option to `resolve_closest`, which allows to resolve the reference to the "closest URL". See the documentation for more information: https://github.com/mkdocstrings/autorefs#non-unique-headings. This PR was done following suggestions in: * mkdocstrings/autorefs#52
2 parents ec166ab + ded52da commit 3842d77

File tree

5 files changed

+168
-116
lines changed

5 files changed

+168
-116
lines changed

docs/user-guide/formula-engine.md

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
# Formula Engine
22

3-
::: frequenz.sdk.timeseries.formula_engine.FormulaEngine
4-
options:
5-
members: None
6-
show_bases: false
7-
show_root_full_path: false
8-
show_source: false
9-
10-
::: frequenz.sdk.timeseries.formula_engine.FormulaEngine3Phase
3+
::: frequenz.sdk.timeseries.formula_engine
114
options:
125
members: None
136
show_bases: false
147
show_root_full_path: false
8+
show_root_heading: false
9+
show_root_toc_entry: false
1510
show_source: false

mkdocs.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ markdown_extensions:
8787
permalink: "¤"
8888

8989
plugins:
90+
- autorefs:
91+
resolve_closest: true
9092
- gen-files:
9193
scripts:
9294
- docs/_scripts/mkdocstrings_autoapi.py

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ dev-mkdocs = [
5454
"black == 24.8.0",
5555
"Markdown==3.7",
5656
"mike == 2.1.3",
57-
"mkdocs-autorefs >= 1.0.1, < 1.1",
5857
"mkdocs-gen-files == 0.5.0",
5958
"mkdocs-literate-nav == 0.6.1",
6059
"mkdocs-macros-plugin == 1.0.5",

src/frequenz/sdk/timeseries/formula_engine/__init__.py

Lines changed: 107 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,114 @@
11
# License: MIT
22
# Copyright © 2023 Frequenz Energy-as-a-Service GmbH
33

4-
"""The formula engine module.
4+
"""Provides a way for the SDK to apply formulas on resampled data streams.
55
6-
This module exposes the
7-
[FormulaEngine][frequenz.sdk.timeseries.formula_engine.FormulaEngine] and
8-
[FormulaEngine3Phase][frequenz.sdk.timeseries.formula_engine.FormulaEngine3Phase]
9-
classes.
6+
# Formula Engine
7+
8+
[`FormulaEngine`][frequenz.sdk.timeseries.formula_engine.FormulaEngine]s are used in the
9+
SDK to calculate and stream metrics like
10+
[`grid_power`][frequenz.sdk.timeseries.grid.Grid.power],
11+
[`consumer_power`][frequenz.sdk.timeseries.consumer.Consumer.power], etc., which are
12+
building blocks of the [Frequenz SDK Microgrid
13+
Model][frequenz.sdk.microgrid--frequenz-sdk-microgrid-model].
14+
15+
The SDK creates the formulas by analysing the configuration of components in the
16+
{{glossary("Component Graph")}}.
17+
18+
## Streaming Interface
19+
20+
The
21+
[`FormulaEngine.new_receiver()`][frequenz.sdk.timeseries.formula_engine.FormulaEngine.new_receiver]
22+
method can be used to create a [Receiver][frequenz.channels.Receiver] that streams the
23+
[Sample][frequenz.sdk.timeseries.Sample]s calculated by the formula engine.
24+
25+
```python
26+
from frequenz.sdk import microgrid
27+
28+
battery_pool = microgrid.new_battery_pool(priority=5)
29+
30+
async for power in battery_pool.power.new_receiver():
31+
print(f"{power=}")
32+
```
33+
34+
## Composition
35+
36+
Composite `FormulaEngine`s can be built using arithmetic operations on
37+
`FormulaEngine`s streaming the same type of data.
38+
39+
For example, if you're interested in a particular composite metric that can be
40+
calculated by subtracting
41+
[`new_battery_pool().power`][frequenz.sdk.timeseries.battery_pool.BatteryPool.power] and
42+
[`new_ev_charger_pool().power`][frequenz.sdk.timeseries.ev_charger_pool.EVChargerPool]
43+
from the
44+
[`grid().power`][frequenz.sdk.timeseries.grid.Grid.power],
45+
we can build a `FormulaEngine` that provides a stream of this calculated metric as
46+
follows:
47+
48+
```python
49+
from frequenz.sdk import microgrid
50+
51+
battery_pool = microgrid.new_battery_pool(priority=5)
52+
ev_charger_pool = microgrid.new_ev_charger_pool(priority=5)
53+
grid = microgrid.grid()
54+
55+
# apply operations on formula engines to create a formula engine that would
56+
# apply these operations on the corresponding data streams.
57+
net_power = (
58+
grid.power - (battery_pool.power + ev_charger_pool.power)
59+
).build("net_power")
60+
61+
async for power in net_power.new_receiver():
62+
print(f"{power=}")
63+
```
64+
65+
# Formula Engine 3-Phase
66+
67+
A [`FormulaEngine3Phase`][frequenz.sdk.timeseries.formula_engine.FormulaEngine3Phase]
68+
is similar to a
69+
[`FormulaEngine`][frequenz.sdk.timeseries.formula_engine.FormulaEngine], except that
70+
they stream [3-phase samples][frequenz.sdk.timeseries.Sample3Phase]. All the
71+
current formulas (like
72+
[`Grid.current_per_phase`][frequenz.sdk.timeseries.grid.Grid.current_per_phase],
73+
[`EVChargerPool.current_per_phase`][frequenz.sdk.timeseries.ev_charger_pool.EVChargerPool.current_per_phase],
74+
etc.) are implemented as per-phase formulas.
75+
76+
## Streaming Interface
77+
78+
The
79+
[`FormulaEngine3Phase.new_receiver()`][frequenz.sdk.timeseries.formula_engine.FormulaEngine3Phase.new_receiver]
80+
method can be used to create a [Receiver][frequenz.channels.Receiver] that streams the
81+
[Sample3Phase][frequenz.sdk.timeseries.Sample3Phase] values
82+
calculated by the formula engine.
83+
84+
```python
85+
from frequenz.sdk import microgrid
86+
87+
ev_charger_pool = microgrid.new_ev_charger_pool(priority=5)
88+
89+
async for sample in ev_charger_pool.current_per_phase.new_receiver():
90+
print(f"Current: {sample}")
91+
```
92+
93+
## Composition
94+
95+
`FormulaEngine3Phase` instances can be composed together, just like `FormulaEngine`
96+
instances.
97+
98+
```python
99+
from frequenz.sdk import microgrid
100+
101+
ev_charger_pool = microgrid.new_ev_charger_pool(priority=5)
102+
grid = microgrid.grid()
103+
104+
# Calculate grid consumption current that's not used by the EV chargers
105+
other_current = (grid.current_per_phase - ev_charger_pool.current_per_phase).build(
106+
"other_current"
107+
)
108+
109+
async for sample in other_current.new_receiver():
110+
print(f"Other current: {sample}")
111+
```
10112
"""
11113

12114
from ._formula_engine import FormulaEngine, FormulaEngine3Phase

src/frequenz/sdk/timeseries/formula_engine/_formula_engine.py

Lines changed: 56 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -57,68 +57,39 @@
5757

5858

5959
class FormulaEngine(Generic[QuantityT]):
60-
"""[`FormulaEngine`][frequenz.sdk.timeseries.formula_engine.FormulaEngine]s are a
61-
part of the SDK's data pipeline, and provide a way for the SDK to apply formulas on
62-
resampled data streams.
60+
"""An engine to apply formulas on resampled data streams.
6361
64-
They are used in the SDK to calculate and stream metrics like
65-
[`grid_power`][frequenz.sdk.timeseries.grid.Grid.power],
66-
[`consumer_power`][frequenz.sdk.timeseries.consumer.Consumer.power],
67-
etc., which are building blocks of the
68-
[Frequenz SDK Microgrid Model][frequenz.sdk.microgrid--frequenz-sdk-microgrid-model].
62+
Please refer to the [module documentation][frequenz.sdk.timeseries.formula_engine]
63+
for more information on how formula engines are used throughout the SDK.
6964
70-
The SDK creates the formulas by analysing the configuration of components in the
71-
{{glossary("Component Graph")}}.
72-
73-
### Streaming Interface
74-
75-
The
76-
[`FormulaEngine.new_receiver()`][frequenz.sdk.timeseries.formula_engine.FormulaEngine.new_receiver]
77-
method can be used to create a
78-
[Receiver](https://frequenz-floss.github.io/frequenz-channels-python/latest/reference/frequenz/channels/#frequenz.channels.Receiver)
79-
that streams the [Sample][frequenz.sdk.timeseries.Sample]s calculated by the formula
80-
engine.
81-
82-
```python
83-
from frequenz.sdk import microgrid
84-
85-
battery_pool = microgrid.new_battery_pool(priority=5)
86-
87-
async for power in battery_pool.power.new_receiver():
88-
print(f"{power=}")
89-
```
90-
91-
### Composition
65+
Example: Streaming the power of a battery pool.
66+
```python
67+
from frequenz.sdk import microgrid
9268
93-
Composite `FormulaEngine`s can be built using arithmetic operations on
94-
`FormulaEngine`s streaming the same type of data.
69+
battery_pool = microgrid.new_battery_pool(priority=5)
9570
96-
For example, if you're interested in a particular composite metric that can be
97-
calculated by subtracting
98-
[`new_battery_pool().power`][frequenz.sdk.timeseries.battery_pool.BatteryPool.power] and
99-
[`new_ev_charger_pool().power`][frequenz.sdk.timeseries.ev_charger_pool.EVChargerPool]
100-
from the
101-
[`grid().power`][frequenz.sdk.timeseries.grid.Grid.power],
102-
we can build a `FormulaEngine` that provides a stream of this calculated metric as
103-
follows:
71+
async for power in battery_pool.power.new_receiver():
72+
print(f"{power=}")
73+
```
10474
105-
```python
106-
from frequenz.sdk import microgrid
75+
Example: Composition of formula engines.
76+
```python
77+
from frequenz.sdk import microgrid
10778
108-
battery_pool = microgrid.new_battery_pool(priority=5)
109-
ev_charger_pool = microgrid.new_ev_charger_pool(priority=5)
110-
grid = microgrid.grid()
79+
battery_pool = microgrid.new_battery_pool(priority=5)
80+
ev_charger_pool = microgrid.new_ev_charger_pool(priority=5)
81+
grid = microgrid.grid()
11182
112-
# apply operations on formula engines to create a formula engine that would
113-
# apply these operations on the corresponding data streams.
114-
net_power = (
115-
grid.power - (battery_pool.power + ev_charger_pool.power)
116-
).build("net_power")
83+
# apply operations on formula engines to create a formula engine that would
84+
# apply these operations on the corresponding data streams.
85+
net_power = (
86+
grid.power - (battery_pool.power + ev_charger_pool.power)
87+
).build("net_power")
11788
118-
async for power in net_power.new_receiver():
119-
print(f"{power=}")
120-
```
121-
""" # noqa: D400, D205
89+
async for power in net_power.new_receiver():
90+
print(f"{power=}")
91+
```
92+
"""
12293

12394
def __init__(
12495
self,
@@ -392,54 +363,37 @@ def new_receiver(
392363

393364

394365
class FormulaEngine3Phase(Generic[QuantityT]):
395-
"""A
396-
[`FormulaEngine3Phase`][frequenz.sdk.timeseries.formula_engine.FormulaEngine3Phase]
397-
is similar to a
398-
[`FormulaEngine`][frequenz.sdk.timeseries.formula_engine.FormulaEngine], except that
399-
they stream [3-phase samples][frequenz.sdk.timeseries.Sample3Phase]. All the
400-
current formulas (like
401-
[`Grid.current_per_phase`][frequenz.sdk.timeseries.grid.Grid.current_per_phase],
402-
[`EVChargerPool.current_per_phase`][frequenz.sdk.timeseries.ev_charger_pool.EVChargerPool.current_per_phase],
403-
etc.) are implemented as per-phase formulas.
404-
405-
### Streaming Interface
406-
407-
The
408-
[`FormulaEngine3Phase.new_receiver()`][frequenz.sdk.timeseries.formula_engine.FormulaEngine3Phase.new_receiver]
409-
method can be used to create a
410-
[Receiver](https://frequenz-floss.github.io/frequenz-channels-python/latest/reference/frequenz/channels/#frequenz.channels.Receiver)
411-
that streams the [Sample3Phase][frequenz.sdk.timeseries.Sample3Phase] values
412-
calculated by the formula engine.
413-
414-
```python
415-
from frequenz.sdk import microgrid
416-
417-
ev_charger_pool = microgrid.new_ev_charger_pool(priority=5)
418-
419-
async for sample in ev_charger_pool.current_per_phase.new_receiver():
420-
print(f"Current: {sample}")
421-
```
422-
423-
### Composition
424-
425-
`FormulaEngine3Phase` instances can be composed together, just like `FormulaEngine`
426-
instances.
427-
428-
```python
429-
from frequenz.sdk import microgrid
430-
431-
ev_charger_pool = microgrid.new_ev_charger_pool(priority=5)
432-
grid = microgrid.grid()
433-
434-
# Calculate grid consumption current that's not used by the EV chargers
435-
other_current = (grid.current_per_phase - ev_charger_pool.current_per_phase).build(
436-
"other_current"
437-
)
438-
439-
async for sample in other_current.new_receiver():
440-
print(f"Other current: {sample}")
441-
```
442-
""" # noqa: D205, D400
366+
"""An engine to apply formulas on 3-phase resampled data streams.
367+
368+
Please refer to the [module documentation][frequenz.sdk.timeseries.formula_engine]
369+
for more information on how formula engines are used throughout the SDK.
370+
371+
Example: Streaming the current of an EV charger pool.
372+
```python
373+
from frequenz.sdk import microgrid
374+
375+
ev_charger_pool = microgrid.new_ev_charger_pool(priority=5)
376+
377+
async for sample in ev_charger_pool.current_per_phase.new_receiver():
378+
print(f"Current: {sample}")
379+
```
380+
381+
Example: Composition of formula engines.
382+
```python
383+
from frequenz.sdk import microgrid
384+
385+
ev_charger_pool = microgrid.new_ev_charger_pool(priority=5)
386+
grid = microgrid.grid()
387+
388+
# Calculate grid consumption current that's not used by the EV chargers
389+
other_current = (grid.current_per_phase - ev_charger_pool.current_per_phase).build(
390+
"other_current"
391+
)
392+
393+
async for sample in other_current.new_receiver():
394+
print(f"Other current: {sample}")
395+
```
396+
"""
443397

444398
def __init__(
445399
self,

0 commit comments

Comments
 (0)