diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index f78d6bb..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4c7cf8c..81ce0e1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.6.2 + rev: v0.5.5 hooks: # Run the linter. - id: ruff @@ -12,7 +12,7 @@ repos: types_or: [python, pyi, jupyter] - repo: https://github.com/asottile/pyupgrade - rev: v3.17.0 + rev: v3.16.0 hooks: - id: pyupgrade args: [--py311-plus] diff --git a/DEVELOPERS.md b/DEVELOPERS.md index 7b936ec..8edef96 100644 --- a/DEVELOPERS.md +++ b/DEVELOPERS.md @@ -52,4 +52,4 @@ other option is to run as root from within the `devcontainer.json` `"remoteUser" > If you’re on an Apple Silicon machine, you’ll need to install [polars](https://pandera.readthedocs.io/en/latest/polars.html) via pip install polars-lts-cpu. > You may have to delete polars if it’s already installed: > `pip uninstall polars` -> `pip install polars-lts-cpu` \ No newline at end of file +> `pip install polars-lts-cpu` diff --git a/data/capacity/capacity_output.json b/data/capacity/capacity_output.json index cbda9ae..fd0162d 100644 --- a/data/capacity/capacity_output.json +++ b/data/capacity/capacity_output.json @@ -5,7 +5,7 @@ "2024-06-13T17:30:00+02:00", "2024-07-02T11:00:00+02:00" ], - "name": "None", + "name": null, "data": [ 2.32, 3.596, @@ -29,7 +29,7 @@ "2024-06-13T18:30:00+02:00", "2024-06-13T18:45:00+02:00" ], - "name": "None", + "name": null, "data": [ 2.104, 0.9, @@ -44,6 +44,37 @@ ] } }, + { + "peak_time": "2024-06-13T17:45:00+02:00", + "peak_value": 3.316, + "surrounding_data": { + "index": [ + "2024-06-13T16:45:00+02:00", + "2024-06-13T17:00:00+02:00", + "2024-06-13T17:15:00+02:00", + "2024-06-13T17:30:00+02:00", + "2024-06-13T17:45:00+02:00", + "2024-06-13T18:00:00+02:00", + "2024-06-13T18:15:00+02:00", + "2024-06-13T18:30:00+02:00", + "2024-06-13T18:45:00+02:00", + "2024-06-13T19:00:00+02:00" + ], + "name": null, + "data": [ + 0.9, + 2.628, + 1.352, + 3.596, + 3.316, + 2.216, + 1.412, + 0.768, + 0.544, + 0.564 + ] + } + }, { "peak_time": "2024-06-24T18:00:00+02:00", "peak_value": 3.048, @@ -60,7 +91,7 @@ "2024-06-24T19:00:00+02:00", "2024-06-24T19:15:00+02:00" ], - "name": "None", + "name": null, "data": [ 0.628, 0.724, @@ -91,7 +122,7 @@ "2024-06-06T01:15:00+02:00", "2024-06-06T01:30:00+02:00" ], - "name": "None", + "name": null, "data": [ 1.324, 1.384, @@ -122,7 +153,7 @@ "2024-07-02T12:00:00+02:00", "2024-07-02T12:15:00+02:00" ], - "name": "None", + "name": null, "data": [ 0.508, 0.7, @@ -137,6 +168,37 @@ ] } }, + { + "peak_time": "2024-06-13T17:00:00+02:00", + "peak_value": 2.628, + "surrounding_data": { + "index": [ + "2024-06-13T16:00:00+02:00", + "2024-06-13T16:15:00+02:00", + "2024-06-13T16:30:00+02:00", + "2024-06-13T16:45:00+02:00", + "2024-06-13T17:00:00+02:00", + "2024-06-13T17:15:00+02:00", + "2024-06-13T17:30:00+02:00", + "2024-06-13T17:45:00+02:00", + "2024-06-13T18:00:00+02:00", + "2024-06-13T18:15:00+02:00" + ], + "name": null, + "data": [ + 0.728, + 1.468, + 2.104, + 0.9, + 2.628, + 1.352, + 3.596, + 3.316, + 2.216, + 1.412 + ] + } + }, { "peak_time": "2024-06-27T23:00:00+02:00", "peak_value": 2.612, @@ -153,7 +215,7 @@ "2024-06-28T00:00:00+02:00", "2024-06-28T00:15:00+02:00" ], - "name": "None", + "name": null, "data": [ 0.74, 0.724, @@ -184,7 +246,7 @@ "2024-06-02T20:15:00+02:00", "2024-06-02T20:30:00+02:00" ], - "name": "None", + "name": null, "data": [ 0.872, 0.888, @@ -200,126 +262,64 @@ } }, { - "peak_time": "2024-06-05T09:15:00+02:00", - "peak_value": 2.464, - "surrounding_data": { - "index": [ - "2024-06-05T08:15:00+02:00", - "2024-06-05T08:30:00+02:00", - "2024-06-05T08:45:00+02:00", - "2024-06-05T09:00:00+02:00", - "2024-06-05T09:15:00+02:00", - "2024-06-05T09:30:00+02:00", - "2024-06-05T09:45:00+02:00", - "2024-06-05T10:00:00+02:00", - "2024-06-05T10:15:00+02:00", - "2024-06-05T10:30:00+02:00" - ], - "name": "None", - "data": [ - 0.612, - 0.484, - 0.444, - 1.528, - 2.464, - 1.884, - 0.864, - 0.628, - 0.552, - 0.608 - ] - } - }, - { - "peak_time": "2024-06-07T10:30:00+02:00", - "peak_value": 2.46, - "surrounding_data": { - "index": [ - "2024-06-07T09:30:00+02:00", - "2024-06-07T09:45:00+02:00", - "2024-06-07T10:00:00+02:00", - "2024-06-07T10:15:00+02:00", - "2024-06-07T10:30:00+02:00", - "2024-06-07T10:45:00+02:00", - "2024-06-07T11:00:00+02:00", - "2024-06-07T11:15:00+02:00", - "2024-06-07T11:30:00+02:00", - "2024-06-07T11:45:00+02:00" - ], - "name": "None", - "data": [ - 0.448, - 0.304, - 0.396, - 0.864, - 2.46, - 1.092, - 0.648, - 0.548, - 1.188, - 1.836 - ] - } - }, - { - "peak_time": "2024-06-29T18:00:00+02:00", - "peak_value": 2.456, + "peak_time": "2024-07-02T11:15:00+02:00", + "peak_value": 2.56, "surrounding_data": { "index": [ - "2024-06-29T17:00:00+02:00", - "2024-06-29T17:15:00+02:00", - "2024-06-29T17:30:00+02:00", - "2024-06-29T17:45:00+02:00", - "2024-06-29T18:00:00+02:00", - "2024-06-29T18:15:00+02:00", - "2024-06-29T18:30:00+02:00", - "2024-06-29T18:45:00+02:00", - "2024-06-29T19:00:00+02:00", - "2024-06-29T19:15:00+02:00" + "2024-07-02T10:15:00+02:00", + "2024-07-02T10:30:00+02:00", + "2024-07-02T10:45:00+02:00", + "2024-07-02T11:00:00+02:00", + "2024-07-02T11:15:00+02:00", + "2024-07-02T11:30:00+02:00", + "2024-07-02T11:45:00+02:00", + "2024-07-02T12:00:00+02:00", + "2024-07-02T12:15:00+02:00", + "2024-07-02T12:30:00+02:00" ], - "name": "None", + "name": null, "data": [ - 0.64, - 0.608, - 0.6, - 1.116, - 2.456, - 1.6, - 1.644, - 1.504, - 0.832, - 0.716 + 0.7, + 0.564, + 0.824, + 2.852, + 2.56, + 2.216, + 1.392, + 0.604, + 0.672, + 0.62 ] } }, { - "peak_time": "2024-06-27T11:15:00+02:00", - "peak_value": 2.428, + "peak_time": "2024-06-06T00:30:00+02:00", + "peak_value": 2.548, "surrounding_data": { "index": [ - "2024-06-27T10:15:00+02:00", - "2024-06-27T10:30:00+02:00", - "2024-06-27T10:45:00+02:00", - "2024-06-27T11:00:00+02:00", - "2024-06-27T11:15:00+02:00", - "2024-06-27T11:30:00+02:00", - "2024-06-27T11:45:00+02:00", - "2024-06-27T12:00:00+02:00", - "2024-06-27T12:15:00+02:00", - "2024-06-27T12:30:00+02:00" + "2024-06-05T23:30:00+02:00", + "2024-06-05T23:45:00+02:00", + "2024-06-06T00:00:00+02:00", + "2024-06-06T00:15:00+02:00", + "2024-06-06T00:30:00+02:00", + "2024-06-06T00:45:00+02:00", + "2024-06-06T01:00:00+02:00", + "2024-06-06T01:15:00+02:00", + "2024-06-06T01:30:00+02:00", + "2024-06-06T01:45:00+02:00" ], - "name": "None", + "name": null, "data": [ - 2.036, - 1.04, - 1.232, - 0.804, - 2.428, - 0.796, - 0.64, - 0.552, - 0.584, - 0.584 + 1.384, + 1.348, + 1.696, + 2.888, + 2.548, + 1.536, + 0.512, + 0.328, + 0.32, + 0.296 ] } } diff --git a/openenergyid/__init__.py b/openenergyid/__init__.py index b8481cb..077163f 100644 --- a/openenergyid/__init__.py +++ b/openenergyid/__init__.py @@ -1,6 +1,6 @@ """Open Energy ID Python SDK.""" -__version__ = "0.1.16" +__version__ = "0.1.18" from .enums import Granularity from .models import TimeDataFrame, TimeSeries diff --git a/openenergyid/dyntar/main.py b/openenergyid/dyntar/main.py index 36bd3c8..0e343a0 100644 --- a/openenergyid/dyntar/main.py +++ b/openenergyid/dyntar/main.py @@ -1,5 +1,6 @@ """Main module of the DynTar package.""" +import numpy as np import pandas as pd from openenergyid.const import ( @@ -122,18 +123,25 @@ def extend_dataframe_with_heatmap(df: pd.DataFrame, inplace: bool = False) -> pd if not inplace: df = df.copy() - heatmap_score_delivered = ( - (df[ELECTRICITY_DELIVERED_SMR2] - df[ELECTRICITY_DELIVERED_SMR3]) - / df[ELECTRICITY_DELIVERED_SMR2] - * (df[RLP_WEIGHTED_PRICE_DELIVERED] - df[PRICE_ELECTRICITY_DELIVERED]) - / df[RLP_WEIGHTED_PRICE_DELIVERED] - ) - heatmap_score_exported = ( - (df[ELECTRICITY_EXPORTED_SMR2] - df[ELECTRICITY_EXPORTED_SMR3]) - / df[ELECTRICITY_EXPORTED_SMR2] - * (df[SPP_WEIGHTED_PRICE_EXPORTED] - df[PRICE_ELECTRICITY_EXPORTED]) - / df[SPP_WEIGHTED_PRICE_EXPORTED] + normalized_energy_delta_delivered = ( + df[ELECTRICITY_DELIVERED_SMR2] - df[ELECTRICITY_DELIVERED_SMR3] + ) / df[ELECTRICITY_DELIVERED_SMR2] + normalized_price_delta_delivered = ( + df[RLP_WEIGHTED_PRICE_DELIVERED] - df[PRICE_ELECTRICITY_DELIVERED] + ) / df[RLP_WEIGHTED_PRICE_DELIVERED] + heatmap_score_delivered = normalized_energy_delta_delivered * normalized_price_delta_delivered + + normalized_energy_delta_exported = ( + df[ELECTRICITY_EXPORTED_SMR2] - df[ELECTRICITY_EXPORTED_SMR3] + ) / df[ELECTRICITY_EXPORTED_SMR2] + normalized_energy_delta_exported = normalized_energy_delta_exported.replace( + [np.inf, -np.inf], np.nan ) + normalized_price_delta_exported = ( + df[SPP_WEIGHTED_PRICE_EXPORTED] - df[PRICE_ELECTRICITY_EXPORTED] + ) / df[SPP_WEIGHTED_PRICE_EXPORTED] + heatmap_score_exported = normalized_energy_delta_exported * normalized_price_delta_exported + heatmap_score_delivered.fillna(0, inplace=True) heatmap_score_exported.fillna(0, inplace=True) diff --git a/openenergyid/dyntar/models.py b/openenergyid/dyntar/models.py index 08b9968..7cc0fe3 100644 --- a/openenergyid/dyntar/models.py +++ b/openenergyid/dyntar/models.py @@ -1,7 +1,7 @@ """Models for dynamic tariff analysis.""" from typing import Literal -from pydantic import Field, conlist +from pydantic import Field, conlist, confloat from openenergyid.models import TimeDataFrame @@ -46,7 +46,7 @@ class DynamicTariffAnalysisInput(TimeDataFrame): ) data: list[ conlist( - item_type=float, + item_type=confloat(allow_inf_nan=True), min_length=len(RequiredColumns.__args__), max_length=len(RequiredColumns.__args__), ) # type: ignore @@ -62,5 +62,9 @@ class DynamicTariffAnalysisOutput(TimeDataFrame): examples=[OutputColumns.__args__], ) data: list[ - conlist(item_type=float, min_length=1, max_length=len(OutputColumns.__args__)) # type: ignore + conlist( + item_type=confloat(allow_inf_nan=True), + min_length=1, + max_length=len(OutputColumns.__args__), + ) # type: ignore ] = Field(examples=[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]) diff --git a/openenergyid/models.py b/openenergyid/models.py index 98706d1..790cec1 100644 --- a/openenergyid/models.py +++ b/openenergyid/models.py @@ -78,13 +78,7 @@ class TimeSeries(TimeSeriesBase): """ name: str | None = None - data: list[float | None] - - # @field_validator("data") - # @classmethod - # def replace_nan_with_none(cls, data: list[float]) -> list[float | None]: - # """Replace NaN values with None.""" - # return [None if pd.isna(value) else value for value in data] + data: list[float] @classmethod def from_pandas(cls, data: pd.Series) -> Self: diff --git a/pyproject.toml b/pyproject.toml index 41222f2..352ac84 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ line-length = 100 [tool.poetry] name = "openenergyid" -version = "0.1.2" # You'll need to set this manually or use a different method for dynamic versioning +version = "0.1.18" # You'll need to set this manually or use a different method for dynamic versioning description = "Open Source Python library for energy analytics and simulations" authors = [ "Jan Pecinovsky ", diff --git a/requirements.txt b/requirements.txt index 81db4f8..317baa0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,6 @@ mypy-extensions==1.0.0 numpy==2.0.1 packaging==24.1 pandas==2.2.2 -pandera==0.20.3 patsy==0.5.6 pydantic-core==2.20.1 pydantic==2.8.2 @@ -13,8 +12,11 @@ pytz==2024.1 scipy==1.14.0 six==1.16.0 statsmodels==0.14.2 -typing-extensions==4.12.2 -tzdata==2024.1 polars==1.5.0 pandera[io,polars]==0.20.3 +typeguard==4.3.0 +typing-extensions==4.12.2 +typing-inspect==0.9.0 +tzdata==2024.1 +wrapt==1.16.0