Skip to content

Commit

Permalink
fix: add pydantic ndarray type
Browse files Browse the repository at this point in the history
Custom serialization and validation for numpy arrays
  • Loading branch information
jsolaas committed Jan 29, 2024
1 parent 5a4021d commit d005ed4
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
from typing import List, Literal, Optional, Union

import numpy as np
from numpy.typing import NDArray
from pydantic import BaseModel, ConfigDict

from libecalc.common.logger import logger
from libecalc.core.consumers.legacy_consumer.consumer_function.types import (
ConsumerFunctionType,
)
from libecalc.core.models.results.base import EnergyFunctionResult
from libecalc.core.utils.array_type import PydanticNDArray


class ConsumerFunctionResultBase(BaseModel):
Expand All @@ -24,16 +24,16 @@ class ConsumerFunctionResultBase(BaseModel):

typ: ConsumerFunctionType

time_vector: NDArray[np.float64]
is_valid: NDArray[np.float64]
energy_usage: NDArray[np.float64]
energy_usage_before_power_loss_factor: Optional[NDArray[np.float64]] = None
condition: Optional[NDArray[np.float64]] = None
power_loss_factor: Optional[NDArray[np.float64]] = None
time_vector: PydanticNDArray
is_valid: PydanticNDArray
energy_usage: PydanticNDArray
energy_usage_before_power_loss_factor: Optional[PydanticNDArray] = None
condition: Optional[PydanticNDArray] = None
power_loss_factor: Optional[PydanticNDArray] = None
energy_function_result: Optional[Union[EnergyFunctionResult, List[EnergyFunctionResult]]] = None

# New! to support fuel to power rate...for e.g. compressors emulating turbine
power: Optional[NDArray[np.float64]] = None
power: Optional[PydanticNDArray] = None
model_config = ConfigDict(arbitrary_types_allowed=True)

@abstractmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from libecalc.common.errors.exceptions import EcalcError, IncompatibleDataError
from libecalc.common.logger import logger
from libecalc.common.utils.rates import Rates
from libecalc.core.utils.array_type import PydanticNDArray
from libecalc.expression import Expression


Expand All @@ -32,7 +33,6 @@ class ConsumerSystemOperationalSettingExpressions(BaseModel):
discharge_pressures: List[Expression]
cross_overs: Optional[List[int]] = None
fluid_densities: Optional[List[Expression]] = None
model_config = ConfigDict(arbitrary_types_allowed=True)

@property
def number_of_consumers(self):
Expand Down Expand Up @@ -75,11 +75,11 @@ class PumpSystemOperationalSettingExpressions(ConsumerSystemOperationalSettingEx
class ConsumerSystemOperationalSetting(BaseModel):
"""Warning! The methods below are fragile to changes in attribute names and types."""

rates: List[NDArray[np.float64]]
suction_pressures: List[NDArray[np.float64]]
discharge_pressures: List[NDArray[np.float64]]
rates: List[PydanticNDArray]
suction_pressures: List[PydanticNDArray]
discharge_pressures: List[PydanticNDArray]
cross_overs: Optional[List[int]] = None
fluid_densities: Optional[List[NDArray[np.float64]]] = None
fluid_densities: Optional[List[PydanticNDArray]] = None
model_config = ConfigDict(arbitrary_types_allowed=True, frozen=True)

@model_validator(mode="after")
Expand Down Expand Up @@ -149,4 +149,4 @@ class CompressorSystemOperationalSetting(ConsumerSystemOperationalSetting):


class PumpSystemOperationalSetting(ConsumerSystemOperationalSetting):
fluid_densities: List[NDArray[np.float64]]
fluid_densities: List[PydanticNDArray]
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class CompressorResult(ConsumerSystemComponentResult):

class ConsumerSystemOperationalSettingResult(BaseModel):
consumer_results: List[ConsumerSystemComponentResult]
model_config = ConfigDict(frozen=True, arbitrary_types_allowed=True)
model_config = ConfigDict(frozen=True)

@property
def total_energy_usage(self) -> NDArray[np.float64]:
Expand Down
3 changes: 2 additions & 1 deletion src/libecalc/core/models/tabulated.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from libecalc.common.units import Unit
from libecalc.core.models.base import BaseModel
from libecalc.core.models.results.base import EnergyFunctionResult
from libecalc.core.utils.array_type import PydanticNDArray
from libecalc.dto.types import EnergyUsageType
from libecalc.expression import Expression

Expand Down Expand Up @@ -97,5 +98,5 @@ class VariableExpression(PydanticBaseModel):

class Variable(PydanticBaseModel):
name: str
values: NDArray[np.float64]
values: PydanticNDArray
model_config = ConfigDict(arbitrary_types_allowed=True)
Empty file.
25 changes: 25 additions & 0 deletions src/libecalc/core/utils/array_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""
Custom pydantic type to allow for serialization and validation of ndarray
"""
import numpy as np
from pydantic import BeforeValidator, PlainSerializer
from typing_extensions import Annotated


def nd_array_custom_before_validator(x):
# custom before validation logic
if isinstance(x, list):
return np.asarray(x)
return x


def nd_array_custom_serializer(x):
# custom serialization logic
return str(x)


PydanticNDArray = Annotated[
np.ndarray,
BeforeValidator(nd_array_custom_before_validator),
PlainSerializer(nd_array_custom_serializer, return_type=str),
]

0 comments on commit d005ed4

Please sign in to comment.