Skip to content

Commit

Permalink
skeleton for validation checks for auto tap
Browse files Browse the repository at this point in the history
Signed-off-by: Martijn Govers <Martijn.Govers@Alliander.com>
  • Loading branch information
mgovers committed Jun 4, 2024
1 parent 47ee9e5 commit 5f7a7cf
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 8 deletions.
9 changes: 6 additions & 3 deletions src/power_grid_model/validation/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def field_str(self) -> str:

class MultiComponentValidationError(ValidationError):
"""
Base class for an error that applies to multiple component, and as a consequence also to multiple fields.
Base class for an error that applies to multiple components, and as a consequence also to multiple fields.
Even if both fields have the same name, they are considered to be different fields and notated as such.
E.g. the two fields `id` fields of the `node` and `line` component: [('node', 'id'), ('line', 'id')].
"""
Expand Down Expand Up @@ -237,9 +237,9 @@ class InvalidEnumValueError(SingleFieldValidationError):
"""

_message = "Field {field} contains invalid {enum} values for {n} {objects}."
enum: Type[Enum]
enum: Union[Type[Enum], List[Type[Enum]]]

def __init__(self, component: str, field: str, ids: List[int], enum: Type[Enum]):
def __init__(self, component: str, field: str, ids: List[int], enum: Union[Type[Enum], List[Type[Enum]]]):
super().__init__(component, field, ids)
self.enum = enum

Expand All @@ -248,6 +248,9 @@ def enum_str(self) -> str:
"""
A string representation of the field to which this error applies.
"""
if isinstance(self.enum, list):
return ",".join(e.__name__ for e in self.enum)

return self.enum.__name__

def __eq__(self, other):
Expand Down
13 changes: 9 additions & 4 deletions src/power_grid_model/validation/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ def all_cross_unique(


def all_valid_enum_values(
data: SingleDataset, component: str, field: str, enum: Type[Enum]
data: SingleDataset, component: str, field: str, enum: Union[Type[Enum], List[Type[Enum]]]
) -> List[InvalidEnumValueError]:
"""
Check that for all records of a particular type of component, the values in the 'field' column are valid values for
Expand All @@ -481,14 +481,19 @@ def all_valid_enum_values(
data (SingleDataset): The input/update data set for all components
component (str): The component of interest
field (str): The field of interest
enum (Type[Enum]): The enum type to validate against
enum (Type[Enum]): The enum type to validate against, or a list of such enum types
Returns:
A list containing zero or one InvalidEnumValueError, listing all ids where the value in the field of interest
was not a valid value in the supplied enum type.
"""
valid = [nan_type(component, field)] + list(enum)
invalid = np.isin(data[component][field], np.array(valid, dtype=np.int8), invert=True)
enums: List[Type[Enum]] = enum if isinstance(enum, list) else [enum]

valid = {nan_type(component, field)}
for enum_type in enums:
valid.update(list(enum_type))

invalid = np.isin(data[component][field], np.array(list(valid), dtype=np.int8), invert=True)
if invalid.any():
ids = data[component]["id"][invalid].flatten().tolist()
return [InvalidEnumValueError(component, field, ids, enum)]
Expand Down
20 changes: 20 additions & 0 deletions src/power_grid_model/validation/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,9 @@ def validate_values(data: SingleDataset, calculation_type: Optional[CalculationT
if calculation_type in (None, CalculationType.short_circuit) and "fault" in data:
errors += validate_fault(data)

if calculation_type in (None, CalculationType.power_flow) and "transformer_tap_regulator" in data:
errors += validate_transformer_tap_regulator(data)

return errors


Expand Down Expand Up @@ -806,3 +809,20 @@ def validate_fault(data: SingleDataset) -> List[ValidationError]:
errors += all_enabled_identical(data, "fault", "fault_type", "status")
errors += all_enabled_identical(data, "fault", "fault_phase", "status")
return errors


def validate_transformer_tap_regulator(data: SingleDataset) -> List[ValidationError]:
errors = validate_base(data, "transformer_tap_regulator")
errors += all_valid_ids(
data,
"transformer_tap_regulator",
field="regulated_object",
ref_components=["transformer", "three_winding_transformer"],
)
errors += all_boolean(data, "transformer_tap_regulator", "status")
errors += all_valid_enum_values(data, "transformer_tap_regulator", "control_side", [BranchSide, Branch3Side])
errors += all_greater_than_or_equal_to_zero(data, "transformer_tap_regulator", "u_set")
errors += all_greater_than_zero(data, "transformer_tap_regulator", "u_band")
errors += all_greater_than_or_equal_to_zero(data, "transformer_tap_regulator", "line_drop_compensation_r")
errors += all_greater_than_or_equal_to_zero(data, "transformer_tap_regulator", "line_drop_compensation_x")
return errors
11 changes: 10 additions & 1 deletion tests/unit/validation/test_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import pytest

from power_grid_model import LoadGenType, initialize_array
from power_grid_model.enum import FaultPhase, FaultType
from power_grid_model.enum import Branch3Side, BranchSide, FaultPhase, FaultType
from power_grid_model.validation.errors import (
ComparisonError,
FaultPhaseError,
Expand Down Expand Up @@ -329,6 +329,15 @@ def test_all_valid_enum_values():
errors = all_valid_enum_values(valid, "sym_load", "type", LoadGenType)
assert not errors

valid = {"transformer_tap_regulator": initialize_array("input", "transformer_tap_regulator", 5)}
valid["transformer_tap_regulator"]["id"] = np.arange(5)
valid["transformer_tap_regulator"]["control_side"] = np.arange(-1, 4)
errors = all_valid_enum_values(valid, "transformer_tap_regulator", "control_side", [BranchSide, Branch3Side])
assert len(errors) == 1
assert (
InvalidEnumValueError("transformer_tap_regulator", "control_side", [0, 4], [BranchSide, Branch3Side]) in errors
)


def test_all_valid_ids():
# This data is for testing purpuse
Expand Down

0 comments on commit 5f7a7cf

Please sign in to comment.