toy-example-reporter.rst 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. .. _tut_toy_schedule_reporter:
  2. Toy example IV: Computing reports
  3. =====================================
  4. So far, we have worked on scheduling batteries and processes. Now, we are moving to one of the other three pillars of FlexMeasures: reporting.
  5. In essence, reporters apply arbitrary transformations to data coming from some sensors (multiple inputs) and save the results to other sensors (multiple outputs). In practice, this allows to compute KPIs (such as profit and total daily energy production), to apply operations to beliefs (e.g. changing the sign of a power sensor for some time period), among other things.
  6. .. note::
  7. Currently, FlexMeasures comes with the following reporters:
  8. - `PandasReporter`: applies arbitrary `Pandas <https://pandas.pydata.org>`_ methods to sensor data.
  9. - `AggregatorReporter`: combines data from multiple sensors into one using any of the methods supported by the Pandas `aggregate` function (e.g. sum, average, max, min...).
  10. - `ProfitOrLossReporter`: computes the profit/loss due to an energy flow under a specific tariff.
  11. Moreover, it's possible to implement your custom reporters in plugins. Instructions for this to come.
  12. Now, coming back to the tutorial, we are going to use the `AggregatorReporter` and the `ProfitOrLossReporter`.
  13. In the first part, we'll use the `AggregatorReporter` to compute the (discharge) headroom of the battery in :ref:`tut_toy_schedule_expanded`. That way, we can verify the maximum power at which the battery can discharge at any point of time.
  14. In the second part, we'll use the `ProfitOrLossReporter` to compute the costs of operating the process of Tut. Part III in the different policies.
  15. Before getting to the meat of the tutorial, we need to set up up all the entities. Instead of having to do that manually (e.g. using commands such as ``flexmeasures add sensor``), we have prepared a command that does that automatically.
  16. Setup
  17. .....
  18. Just as in previous sections, we need to run the command ``flexmeasures add toy-account``, but this time with a different value for *kind*:
  19. .. code-block:: bash
  20. $ flexmeasures add toy-account --kind reporter
  21. Under the hood, this command is adding the following entities:
  22. - A sensor that stores the capacity of the grid connection (with a resolution of one year, so storing just one value:) ).
  23. - A power sensor, `headroom`, to store the remaining capacity for the battery. This is where we'll store the report.
  24. - A `ProfitOrLossReporter` configured to use the prices that we set up in Tut. Part II.
  25. - Three sensors to register the profits/losses from running the three different processes of Tut. Part III.
  26. .. note:: The above command should also print out the IDs of these sensors. We will use these IDs verbatim in this tutorial.
  27. Let's check it out!
  28. Run the command below to show the values for our newly-created `grid connection capacity`:
  29. .. code-block:: bash
  30. $ TOMORROW=$(date --date="next day" '+%Y-%m-%d')
  31. $ flexmeasures show beliefs --sensor 7 --start ${TOMORROW}T00:00:00+02:00 --duration PT24H --resolution PT1H
  32. Beliefs for Sensor 'grid connection capacity' (ID 7).
  33. Data spans a day and starts at 2023-08-14 00:00:00+02:00.
  34. The time resolution (x-axis) is an hour.
  35. ┌────────────────────────────────────────────────────────────┐
  36. │ │
  37. │ │
  38. │ │
  39. │ │
  40. │ │ 1.0MW
  41. │ │
  42. │ │
  43. │ │
  44. │▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀│ 0.5MW
  45. │ │
  46. │ │
  47. │ │
  48. │▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁│ 0.0MW
  49. │ │
  50. │ │
  51. │ │
  52. │ │ -0.5MW
  53. └────────────────────────────────────────────────────────────┘
  54. 5 10 15 20
  55. ██ grid connection capacity
  56. Moreover, we can check the freshly created source `<Source id=6>`, which defines the `ProfitOrLossReporter` with the required configuration.
  57. You'll notice that the `config` is under the `data_generator` field.
  58. That's because reporters belong to a bigger category of classes that also contains the `Schedulers` and `Forecasters`.
  59. .. code-block:: bash
  60. $ flexmeasures show data-sources --show-attributes --id 6
  61. type: reporter
  62. ========
  63. ID Name User ID Model Version Attributes
  64. ---- ------------ --------- -------------------- --------- ------------------------------------------
  65. 6 FlexMeasures ProfitOrLossReporter {
  66. "data_generator": {
  67. "config": {
  68. "consumption_price_sensor": 1,
  69. "loss_is_positive": true
  70. }
  71. }
  72. }
  73. Compute headroom
  74. -------------------
  75. In this case, the discharge headroom is nothing but the difference between the grid connection capacity and the PV power.
  76. To compute that quantity, we can use the `AggregatorReporter` using the weights to make the PV to subtract the grid connection capacity.
  77. In practice, we need to create the `config` and `parameters`:
  78. .. code-block:: bash
  79. $ echo "
  80. $ {
  81. $ 'weights' : {
  82. $ 'grid connection capacity' : 1.0,
  83. $ 'PV' : -1.0,
  84. $ }
  85. $ }" > headroom-config.json
  86. .. code-block:: bash
  87. $ echo "
  88. $ {
  89. $ 'input' : [{'name' : 'grid connection capacity','sensor' : 7},
  90. $ {'name' : 'PV', 'sensor' : 3}],
  91. $ 'output' : [{'sensor' : 8}]
  92. $ }" > headroom-parameters.json
  93. The output sensor (ID: 8) is actually the one created just to store that information - the headroom our battery has when considering solar production.
  94. Finally, we can create the report with the following command:
  95. .. code-block:: bash
  96. $ flexmeasures add report --reporter AggregatorReporter \
  97. --parameters headroom-parameters.json --config headroom-config.json \
  98. --start-offset DB,1D --end-offset DB,2D \
  99. --resolution PT15M
  100. Now we can visualize the diminished headroom in the following `link <http://localhost:5000/sensors/8/graphs>`_, which should resemble the following image:
  101. .. image:: https://github.com/FlexMeasures/screenshots/raw/main/tut/toy-schedule/sensor-data-headroom.png
  102. :align: center
  103. |
  104. The graph shows that the capacity of the grid is at full disposal for the battery when there's no sun (thus no PV generation), while at noon the battery can only discharge at 280kW max.
  105. Process scheduler profit
  106. -------------------------
  107. For the second part of this tutorial, we are going to use the `ProfitOrLossReporter` to compute the losses (defined as `cost - revenue`) of operating the process from Tut.
  108. Part III, under the three different policies: INFLEXIBLE, BREAKABLE and SHIFTABLE.
  109. In addition, we'll explore another way to invoke reporters: data generators.
  110. Without going too much into detail, data generators create new data.
  111. The thee main types are: `Reporters`, `Schedulers` and `Forecasters`.
  112. This will come handy as the three reports that we are going to create share the same `config`.
  113. The `config` defines the price sensor to use and sets the reporter to work in **losses** mode, which means that it will return costs as positive values and revenue as negative values.
  114. Still, we need to define the parameters.
  115. The three reports share the same structure for the parameters with the following fields:
  116. - `input`: sensor that stores the power/energy flow. The number of sensors is limited to 1.
  117. - `output`: sensor to store the report. We can provide sensors with different resolutions to store the same results at different time scales.
  118. .. note::
  119. It's possible to define the `config` and `parameters` in JSON or YAML formats.
  120. After setting up `config` and `parameters`, we can invoke the reporter using the command ``flexmeasures add report``.
  121. The command takes the data source id, the files containing the parameters and the timing parameters (start and end).
  122. For this particular case, we make use of the offsets to indicate that we want the report to encompass the day of tomorrow.
  123. Inflexible process
  124. ^^^^^^^^^^^^^^^^^^^
  125. Define parameters in a JSON file:
  126. .. code-block:: bash
  127. $ echo "
  128. $ {
  129. $ 'input' : [{'sensor' : 4}],
  130. $ 'output' : [{'sensor' : 9}]
  131. $ }" > inflexible-parameters.json
  132. Create report:
  133. .. code-block:: bash
  134. $ flexmeasures add report --source 6 \
  135. --parameters inflexible-parameters.json \
  136. --start-offset DB,1D --end-offset DB,2D
  137. Check the results `here <http://localhost:5000/sensors/9>`_. The image should be similar to the one below.
  138. .. image:: https://github.com/FlexMeasures/screenshots/raw/main/tut/toy-schedule/sensor-data-inflexible.png
  139. :align: center
  140. |
  141. Breakable process
  142. ^^^^^^^^^^^^^^^^^^^
  143. Define parameters in a JSON file:
  144. .. code-block:: bash
  145. $ echo "
  146. $ {
  147. $ 'input' : [{'sensor' : 5}],
  148. $ 'output' : [{'sensor' : 10}]
  149. $ }" > breakable-parameters.json
  150. Create report:
  151. .. code-block:: bash
  152. $ flexmeasures add report --source 6 \
  153. --parameters breakable-parameters.json \
  154. --start-offset DB,1D --end-offset DB,2D
  155. Check the results `here <http://localhost:5000/sensors/10>`_. The image should be similar to the one below.
  156. .. image:: https://github.com/FlexMeasures/screenshots/raw/main/tut/toy-schedule/sensor-data-breakable.png
  157. :align: center
  158. |
  159. Shiftable process
  160. ^^^^^^^^^^^^^^^^^^^
  161. Define parameters in a JSON file:
  162. .. code-block:: bash
  163. $ echo "
  164. $ {
  165. $ 'input' : [{'sensor' : 6}],
  166. $ 'output' : [{'sensor' : 11}]
  167. $ }" > shiftable-parameters.json
  168. Create report:
  169. .. code-block:: bash
  170. $ flexmeasures add report --source 6 \
  171. --parameters shiftable-parameters.json \
  172. --start-offset DB,1D --end-offset DB,2D
  173. Check the results `here <http://localhost:5000/sensors/11>`_. The image should be similar to the one below.
  174. .. image:: https://github.com/FlexMeasures/screenshots/raw/main/tut/toy-schedule/sensor-data-shiftable.png
  175. :align: center
  176. |
  177. Now, we can compare the results of the reports to the ones we computed manually in :ref:`this table <table-process>`). Keep in mind that the
  178. report is showing the profit of each 15min period and adding them all shows that it matches with our previous results.