Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ import equinox as eqx

class MyData(eqx.Module):
traced_array: Float[Array, " n"] # JAX will trace this
static_config: Static[int] = eqx.field(static=True) # JAX won't trace this
static_config: int = eqx.field(static=True) # JAX won't trace this
```

**HDF5 Persistence**: Large matrices stored in `.hdf5` via `h5py`. See `dc_solver_pkg/jax/inputs.py` for save/load patterns. Paths in `interfaces_pkg/folder_structure.py`.
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM ghcr.io/astral-sh/uv:0.11.16@sha256:440fd6477af86a2f1b38080c539f1672cd22acb1b1a47e321dba5158ab08864d AS uv

FROM python:3.13.6-bullseye@sha256:f58f33e0563f2ba81c7afe6259cd912f0c33413da93c75cc3a70a941c17afa8c
FROM python:3.14.3@sha256:9234c2fd80143741d28153f66dc306f0448c477a7d965df83107373411509357

# Declare environment variables
ENV PATH="/root/.local/bin:$PATH"
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


[![License: MPL 2.0](https://img.shields.io/badge/License-MPL_2.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0)
[![Python 3.11](https://img.shields.io/badge/python-3.11-blue.svg)](https://www.python.org/downloads/release/python-3110/)
[![Python 3.14](https://img.shields.io/badge/python-3.14-blue.svg)](https://www.python.org/downloads/release/python-3140/)
<!-- markdown-link-check-enable -->

## Hello there 👋
Expand Down Expand Up @@ -45,8 +45,10 @@ If you want to contribute to this repository, we recommend using VS Code's Devco

For this setup, you need to install:
1. `uv`
2. `Microsoft VS Code`
3. `Docker`
2. `Python 3.14`
3. `CMake 3.x` for native installs outside the devcontainer
4. `Microsoft VS Code`
5. `Docker`

### Installation

Expand Down
3 changes: 3 additions & 0 deletions docs/contribution_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ We provide a [Development Container](https://containers.dev/) configuration that

- [Docker](https://www.docker.com/get-started) installed and running
- [VS Code](https://code.visualstudio.com/) with the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
- Python 3.14 for native development outside the devcontainer

### Getting Started

Expand Down Expand Up @@ -80,6 +81,8 @@ For that, we provide [commit message types](./contribution_guide.md#commit-types

1. **Fork and install**:
```bash
python3.14 -m venv .venv
source .venv/bin/activate
git clone https://github.com/<your-username>/ToOp.git
cd ToOp
uv sync
Expand Down
5 changes: 3 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ If you want to contribute to this repository, we recommend using VS Code's Devco

For this setup, you need to install:
1. `uv`
2. `Microsoft VS Code`
3. `Docker`
2. `Python 3.14`
3. `Microsoft VS Code`
4. `Docker`

### Installation

Expand Down
12 changes: 6 additions & 6 deletions packages/contingency_analysis_pkg/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,17 @@ classifiers=[
'Natural Language :: English',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3.11'
'Programming Language :: Python :: 3.14'
]

requires-python = ">=3.11,<3.12"
requires-python = ">=3.14,<3.15"

[tool.hatch.metadata.hooks.uv-dynamic-versioning]
dependencies = [
"pandera[polars] (>=0.22.1,<0.23.0)",
"pandera[polars] (>=0.26.1,<0.27.0)",
"ray (>=2.42.1,<3.0.0)",
"beartype (>=0.22.0,<0.23.0)",
"numpy (>=1.26.0,<2.0.0)",
"numpy (>=2.1.0,<3.0.0)",
"pandas (>=2.2.3,<3.0.0)",
"pydantic (>=1.10.3,<3.0.0)",
"confluent-kafka (>=2.3.0,<3.0.0)",
Expand All @@ -62,7 +62,7 @@ source = "uv-dynamic-versioning"

[project.optional-dependencies]
pypowsybl = ["pypowsybl>=1.15.0"]
pandapower = ["pandapower>=3.0.0"]
pandapower = ["pandapower>=3.4.0", "lxml>=5.0.0"]

[dependency-groups]
dev = [
Expand All @@ -84,7 +84,7 @@ dev = [
"types-confluent-kafka>=1.3.3",
"pypowsybl-jupyter>=1.0.0",
"docker>=7.1.0",
"numba>=0.61.2",
"numba>=0.65.0,<0.66.0",
"orjson>=3.11.3",
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import dataclasses

import pandapower as pp
import pandera as pa
import pandas as pd
import pandera
import pandera.pandas as pa
import pandera.typing as pat
from beartype.typing import Any, Literal, Optional
from pandera.typing import Index, Series
Expand All @@ -32,6 +34,31 @@
)


def _register_missing_pandera_checks() -> None:
"""Register missing pandas backends for builtin Pandera checks used in this module."""
try:
isin_dispatcher = pa.Check.get_builtin_check_fn("isin")
except Exception:
isin_dispatcher = None

if pd.Series in getattr(isin_dispatcher, "_function_registry", {}):
return

assert tuple(map(int, pandera.__version__.split(".")[:2])) < (0, 27), (
"Remove the temporary Pandera builtin-check registration once Pandera >= 0.27 is supported."
)

@pa.Check.register_builtin_check_fn
def isin(
data: pd.Series,
allowed_values: list[object] | tuple[object, ...],
) -> pd.Series:
return data.isna() | data.isin(allowed_values)


_register_missing_pandera_checks()


class CascadeConfig(BaseModel):
"""Configuration for cascading protection screening after contingency load flow."""

Expand Down Expand Up @@ -98,7 +125,7 @@ class PandapowerMonitoredElementSchema(pa.DataFrameModel):
table: Series[str] = pa.Field(description="The type of the monitored element, e.g. 'line', 'bus', 'load', etc.")
table_id: Series[int] = pa.Field(description="The id of the monitored element in the corresponding table.")
kind: Series[str] = pa.Field(
isin=["branch", "bus", "injection", "switch"],
isin=("branch", "bus", "injection", "switch"),
description="The kind of the monitored element, e.g. 'branch', 'bus' etc.",
)
name: Series[str] = pa.Field(description="The name of the monitored element, if available.")
Expand Down Expand Up @@ -172,7 +199,7 @@ class PandapowerContingencyGroup(BaseModel):
class SppsConditionsPandapowerSchema(pa.DataFrameModel):
"""Pandera schema for resolved SpPS condition rows (one row per condition)."""

scheme_name: Series[str]
scheme_name: Series[str] = pa.Field()
"""Name of the rule scheme: conditions with the same name are evaluated as one logical group."""

condition_logic: Series[str] = pa.Field(isin=SPPS_CONDITION_LOGIC_VALUES)
Expand All @@ -198,7 +225,7 @@ class SppsConditionsPandapowerSchema(pa.DataFrameModel):
)
"""Threshold value for the condition (empty for state-based checks)."""

condition_element_table: Series[str]
condition_element_table: Series[str] = pa.Field()
"""Pandapower table containing the element to monitor."""

condition_element_table_id: Series[int] = pa.Field(coerce=True)
Expand All @@ -217,16 +244,16 @@ class SppsConditionsPandapowerSchema(pa.DataFrameModel):
class SppsActionsPandapowerSchema(pa.DataFrameModel):
"""Pandera schema for resolved SpPS action rows (one row per action)."""

scheme_name: Series[str]
scheme_name: Series[str] = pa.Field()
"""Name of the rule scheme: actions apply when that scheme's conditions pass per ``condition_logic``."""

measure_type: Series[str] = pa.Field(isin=SPPS_MEASURE_TYPE_VALUES)
"""What is applied when the scheme activates."""

measure_value: Series[object]
measure_value: Series[object] = pa.Field()
"""Target value (number or switch state like 'Open'/'Closed')."""

measure_element_table: Series[str]
measure_element_table: Series[str] = pa.Field()
"""Pandapower table containing the element to control."""

measure_element_table_id: Series[int] = pa.Field(coerce=True)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -434,14 +434,16 @@ def add_name_column_polars(
LoadflowResultTablePolars
The updated dataframe with the ids translated to the original names.
"""
fallback_name = pl.col(f"{index_level}_name").cast(pl.String).fill_null("").replace(["NaN", "nan"], ["", ""])

result_df = result_df.with_columns(
pl.col(index_level)
.replace(name_map, default=pl.col(f"{index_level}_name").fill_null(""))
.alias(f"{index_level}_name")
pl.col(index_level).replace(name_map, default=fallback_name).alias(f"{index_level}_name")
)

# fill nulls with empty string
result_df = result_df.with_columns(pl.col(f"{index_level}_name").fill_null(""))
result_df = result_df.with_columns(
pl.col(f"{index_level}_name").cast(pl.String).fill_null("").replace(["NaN", "nan"], ["", ""])
)
return result_df


Expand Down
2 changes: 1 addition & 1 deletion packages/contingency_analysis_pkg/tests/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
def test_int_check_win32(monkeypatch):
# Check pandera version
pandera_version = tuple(map(int, pandera.__version__.split(".")))
assert pandera_version < (0, 23), "Check if this Patch is still needed"
assert pandera_version < (0, 27), "Check if this Patch is still needed"
# Patch sys.platform to 'win32'
monkeypatch.setattr(sys, "platform", "win32")
importlib.reload(sys.modules["toop_engine_contingency_analysis.__init__"])
Expand Down
Loading
Loading