Skip to content

Commit

Permalink
Modification of the docstings and mypy compliant
Browse files Browse the repository at this point in the history
  • Loading branch information
pesap committed Aug 2, 2024
1 parent 4f6f50f commit e019bc4
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 155 deletions.
9 changes: 9 additions & 0 deletions docs/reference/api/function_data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
```{eval-rst}
.. _function-data-api:
```
# Function data

```{eval-rst}
.. automodule:: infrasys.function_data
:members:
```
1 change: 1 addition & 0 deletions docs/reference/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
time_series
location
quantities
function_data
```
4 changes: 4 additions & 0 deletions src/infrasys/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ class ISNotStored(ISBaseException):

class ISOperationNotAllowed(ISBaseException):
"""Raised if the requested operation is not allowed."""


class ISMethodError(ISBaseException):
"""Rased if the requested method is not allowed."""
84 changes: 45 additions & 39 deletions src/infrasys/function_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,43 +18,47 @@ class XYCoords(NamedTuple):
class LinearFunctionData(Component):
"""Data representation for linear cost function.
Class to represent the underlying data of linear functions. Principally used for
the representation of cost functions `f(x) = proportional_term*x + constant_term`.
Used to represent linear cost functions of the form
.. math:: f(x) = mx + c,
where :math:`m` is the proportional term and :math:`c` is the constant term.
"""

name: Annotated[str, Field(frozen=True)] = ""
proportional_term: Annotated[
float, Field(description="the proportional term in the represented function")
float, Field(description="the proportional term in the represented function.")
]
constant_term: Annotated[
float, Field(description="the constant term in the represented function")
float, Field(description="the constant term in the represented function.")
]


class QuadraticFunctionData(Component):
"""Data representation for quadratic cost functions.
"""Data representation for quadratic cost function.
Used to represent quadratic of cost functions of the form
Class to represent the underlying data of quadratic functions. Principally used for the
representation of cost functions
`f(x) = quadratic_term*x^2 + proportional_term*x + constant_term`.
.. math:: f(x) = ax^2 + bx + c,
where :math:`a` is the quadratic term, :math:`b` is the proportional term and :math:`c` is the constant term.
"""

name: Annotated[str, Field(frozen=True)] = ""
quadratic_term: Annotated[
float, Field(description="the quadratic term in the represented function")
float, Field(description="the quadratic term in the represented function.")
]
proportional_term: Annotated[
float, Field(description="the proportional term in the represented function")
float, Field(description="the proportional term in the represented function.")
]
constant_term: Annotated[
float, Field(description="the constant term in the represented function")
float, Field(description="the constant term in the represented function.")
]


def validate_piecewise_linear_x(points: List[XYCoords]) -> List[XYCoords]:
"""Validates the x data for PiecewiseLinearData class
Function used to validate given x data for the PiecewiseLinearData class.
X data is checked to ensure there is at least two values of x,
which is the minimum required to generate a cost curve, and is
given in ascending order (e.g. [1, 2, 3], not [1, 3, 2]).
Expand All @@ -65,28 +69,27 @@ def validate_piecewise_linear_x(points: List[XYCoords]) -> List[XYCoords]:
List of named tuples of (x,y) coordinates for cost function
Returns
----------
-------
points : List[XYCoords]
List of (x,y) data for cost function after successful validation.
"""

x_coords = [p.x for p in points]

if len(x_coords) < 2:
raise ValueError("Must specify at least two x-coordinates")
raise ValueError("Must specify at least two x-coordinates.")
if not (
x_coords == sorted(x_coords)
or (np.isnan(x_coords[0]) and x_coords[1:] == sorted(x_coords[1:]))
):
raise ValueError(f"Piecewise x-coordinates must be ascending, got {x_coords}")
raise ValueError(f"Piecewise x-coordinates must be ascending, got {x_coords}.")

return points


def validate_piecewise_step_x(x_coords: List[float]) -> List[float]:
"""Validates the x data for PiecewiseStepData class
Function used to validate given x data for the PiecewiseStepData class.
X data is checked to ensure there is at least two values of x,
which is the minimum required to generate a cost curve, and is
given in ascending order (e.g. [1, 2, 3], not [1, 3, 2]).
Expand All @@ -97,69 +100,72 @@ def validate_piecewise_step_x(x_coords: List[float]) -> List[float]:
List of x data for cost function.
Returns
----------
-------
x_coords : List[float]
List of x data for cost function after successful validation.
"""

if len(x_coords) < 2:
raise ValueError("Must specify at least two x-coordinates")
raise ValueError("Must specify at least two x-coordinates.")
if not (
x_coords == sorted(x_coords)
or (np.isnan(x_coords[0]) and x_coords[1:] == sorted(x_coords[1:]))
):
raise ValueError(f"Piecewise x-coordinates must be ascending, got {x_coords}")
raise ValueError(f"Piecewise x-coordinates must be ascending, got {x_coords}.")

return x_coords


class PiecewiseLinearData(Component):
"""Data representation for piecewise linear cost function.
Class to represent piecewise linear data as a series of points: two points define one
segment, three points define two segments, etc. The curve starts at the first point given,
not the origin. Principally used for the representation of cost functions where the points
store quantities (x, y), such as (MW, USD/h).
Used to represent linear data as a series of points: two points define one
segment, three points define two segments, etc. The curve starts at the first point given, not the origin.
Principally used for the representation of cost functions where the points store quantities (x, y), such as (MW, USD/h).
"""

name: Annotated[str, Field(frozen=True)] = ""
points: Annotated[
List[XYCoords],
AfterValidator(validate_piecewise_linear_x),
Field(description="list of (x,y) points that define the function"),
Field(description="list of (x,y) points that define the function."),
]


class PiecewiseStepData(Component):
"""Data representation for piecewise step cost function.
Class to represent a step function as a series of endpoint x-coordinates and segment
y-coordinates: two x-coordinates and one y-coordinate defines a single segment, three
x-coordinates and two y-coordinates define two segments, etc. This can be useful to
represent the derivative of a `PiecewiseLinearData`, where the y-coordinates of this
step function represent the slopes of that piecewise linear function.
Used to represent a step function as a series of endpoint x-coordinates and segment
y-coordinates: two x-coordinates and one y-coordinate defines a single segment, three x-coordinates and
two y-coordinates define two segments, etc.
This can be useful to represent the derivative of a
:class:`PiecewiseLinearData`, where the y-coordinates of this step function
represent the slopes of that piecewise linear function.
Principally used for the representation of cost functions where the points store
quantities (x, dy/dx), such as (MW, USD/MWh).
quantities (x, :math:`dy/dx`), such as (MW, USD/MWh).
"""

name: Annotated[str, Field(frozen=True)] = ""
x_coords: Annotated[
List[float],
Field(description="the x-coordinates of the endpoints of the segments"),
Field(description="the x-coordinates of the endpoints of the segments."),
]
y_coords: Annotated[
List[float],
Field(
description="the y-coordinates of the segments: `y_coords[1]` is the y-value \
between `x_coords[0]` and `x_coords[1]`, etc. Must have one fewer elements than `x_coords`."
description=(
"The y-coordinates of the segments: `y_coords[1]` is the y-value between `x_coords[0]` and `x_coords[1]`, etc. "
"Must have one fewer elements than `x_coords`."
)
),
]

@model_validator(mode="after")
def validate_piecewise_xy(self):
"""Method to validate the x and y data for PiecewiseStepData class
Model validator used to validate given data for the PiecewiseStepData class.
Model validator used to validate given data for the :class:`PiecewiseStepData`.
Calls `validate_piecewise_step_x` to check if `x_coords` is valid, then checks if
the length of `y_coords` is exactly one less than `x_coords`, which is necessary
to define the cost functions correctly.
Expand All @@ -175,14 +181,13 @@ def validate_piecewise_xy(self):
def get_slopes(vc: List[XYCoords]) -> List[float]:
"""Calculate slopes from XYCoord data
Function used to calculate the slopes from a list of XYCoords.
Slopes are calculated between each section of the piecewise curve.
Returns a list of slopes that can be used to define Value Curves.
Parameters
----------
vc : List[XYCoords]
List of named tuples of (x,y) coordinates.
List of named tuples of (x, y) coordinates.
Returns
----------
Expand Down Expand Up @@ -216,9 +221,10 @@ def get_x_lengths(x_coords: List[float]) -> List[float]:
def running_sum(data: PiecewiseStepData) -> List[XYCoords]:
"""Calculates y-values from slope data in PiecewiseStepData
Uses the x coordinates and slope data in PiecewiseStepData to
calculate the corresponding y-values, such that:
`y[i] = y[i-1] + slope[i-1]*(x[i] - x[i-1])`
Uses the x coordinates and slope data in PiecewiseStepData to calculate the corresponding y-values, such that:
.. math:: y(i) = y(i-1) + \\text{slope}(i-1) \\times \\left( x(i) - x(i-1) \\right)
Parameters
----------
Expand Down
Loading

0 comments on commit e019bc4

Please sign in to comment.