Skip to content

Mixins

Composable base classes that provide validation, serialization, plotting, coordinate geometry, datetime handling, change propagation, and more.


Colors

Classes

ColorMixin

A class to manage colors, including conversion between hex and RGB formats, and generating color gradients.

Methods:
rgb_tuple_to_hex staticmethod
rgb_tuple_to_hex(rgb: tuple[int, int, int]) -> str

Convert an (R, G, B) tuple to a hex colour string.

get_colorway staticmethod
get_colorway(color1: str, color2: str, n: int) -> list[str]

Generate a list of n hex colors interpolated between two HTML hex colors.

PARAMETER DESCRIPTION
color1

The first color in HTML hex format (e.g., '#ff0000').

TYPE: str

color2

The second color in HTML hex format (e.g., '#0000ff').

TYPE: str

n

The number of colors to generate in the gradient.

TYPE: int

adjust_fill_opacity staticmethod
adjust_fill_opacity(color_str: str, opacity: float) -> str

Adjust the fill opacity of any color format while preserving line opacity.

PARAMETER DESCRIPTION
color_str

Color in any format (hex, rgb, rgba, named).

TYPE: str

opacity

Target opacity (0.0 to 1.0).

TYPE: float

RETURNS DESCRIPTION
str

Color string with adjusted opacity in rgba format.

get_color_format staticmethod
get_color_format(color_str: str) -> str

Detect the format of a color string.

PARAMETER DESCRIPTION
color_str

Color string in any format.

TYPE: str

RETURNS DESCRIPTION
str

Color format: 'hex', 'rgb', 'rgba', 'hsl', 'hsla', 'named', or 'unknown'.

validate_opacity staticmethod
validate_opacity(opacity: float, param_name: str = 'opacity') -> None

Validate that opacity is within valid range.

PARAMETER DESCRIPTION
opacity

Opacity value to validate.

TYPE: float

param_name

Parameter name for error messages.

TYPE: str DEFAULT: 'opacity'

RAISES DESCRIPTION
ValueError

If opacity is not between 0.0 and 1.0.

adjust_trace_opacity staticmethod
adjust_trace_opacity(trace, opacity: float) -> None

Adjust opacity of a plotly trace in-place.

PARAMETER DESCRIPTION
trace

The plotly trace to modify.

opacity

Target opacity (0.0 to 1.0).

TYPE: float


Coordinates

Classes

CoordinateMixin

A class to manage and manipulate 3D coordinates. Provides methods for rotation, area calculation, and coordinate ordering.

Methods:
get_radius_of_points staticmethod
get_radius_of_points(coords: ndarray) -> Tuple[float, Tuple[float, float]]

Calculate the radius of a spiral given its coordinates.

PARAMETER DESCRIPTION
coords

Array of shape (N, 2) with columns [x, z].

TYPE: ndarray

RETURNS DESCRIPTION
Tuple[float, Tuple[float, float]]

(radius, (center_x, center_z)) where radius is in meters.

RAISES DESCRIPTION
ValueError

If input coordinates are invalid or insufficient valid points.

get_xz_center_line staticmethod
get_xz_center_line(coordinates: ndarray) -> ndarray

Generate center line(s) for coordinate data, handling both single and multi-segment polygons.

PARAMETER DESCRIPTION
coordinates

Array of 3D coordinates with shape (N, 3) where columns are [x, y, z]. NaN values in x or z coordinates indicate breaks between polygon segments.

TYPE: ndarray

RETURNS DESCRIPTION
ndarray

For single polygon: Array with shape (2, 2) containing start and end points.

ndarray

For multiple segments: Array with center lines for each segment separated by [NaN, NaN].

ndarray

For empty coordinates: Empty array with shape (0, 2).

rotate_coordinates staticmethod
rotate_coordinates(coords: ndarray, axis: str, angle: float, center: tuple = None) -> ndarray

Rotate a NumPy array of coordinates around the specified axis. Can handle 2D coordinates (N, 2) for x, y or 3D coordinates (N, 3) for x, y, z. Can handle coordinates with None values (preserves None positions).

:param coords: NumPy array of shape (N, 2) for 2D or (N, 3) for 3D coordinates :param axis: Axis to rotate around ('x', 'y', or 'z'). For 2D arrays, only 'z' is valid. :param angle: Angle in degrees :param center: Point to rotate around. For 2D: (x, y) tuple. For 3D: (x, y, z) tuple. If None, rotates around origin. :return: Rotated NumPy array with same shape as input

build_square_array staticmethod
build_square_array(x: float, y: float, x_width: float, y_width: float) -> Tuple[ndarray, ndarray]

Build a NumPy array representing a square or rectangle defined by its bottom-left corner (x, y) and its width and height.

PARAMETER DESCRIPTION
x

The x-coordinate of the bottom-left corner of the square.

TYPE: float

y

The y-coordinate of the bottom-left corner of the square.

TYPE: float

x_width

The width of the square.

TYPE: float

y_width

The height of the square.

TYPE: float

RETURNS DESCRIPTION
Tuple[ndarray, ndarray]

Tuple containing x and y coordinate arrays defining the square/rectangle.

build_circle_array staticmethod
build_circle_array(center_x: float, center_y: float, radius: float, num_points: int = 64, anticlockwise: bool = True) -> Tuple[ndarray, ndarray]

Build a NumPy array representing a circle defined by its center and radius.

PARAMETER DESCRIPTION
center_x

The x-coordinate of the circle center.

TYPE: float

center_y

The y-coordinate of the circle center.

TYPE: float

radius

The radius of the circle.

TYPE: float

num_points

Number of points to use for the circle approximation. Defaults to 64.

TYPE: int DEFAULT: 64

anticlockwise

If True, points are ordered anticlockwise; if False, clockwise. Defaults to True.

TYPE: bool DEFAULT: True

RETURNS DESCRIPTION
Tuple[ndarray, ndarray]

Tuple containing x and y coordinate arrays defining the circle.

order_coordinates_clockwise_numpy staticmethod
order_coordinates_clockwise_numpy(coords: ndarray, plane: str = 'xy') -> ndarray

Order 3D coordinates in clockwise direction based on a specified plane. Handles multiple coordinate blocks separated by NaN rows.

PARAMETER DESCRIPTION
coords

Array of 3D coordinates with shape (N, 3) where columns are [x, y, z]. NaN rows indicate separations between coordinate blocks.

TYPE: ndarray

plane

Plane to use for ordering ('xy', 'xz', 'yz'). Defaults to 'xy'.

TYPE: str DEFAULT: 'xy'

RETURNS DESCRIPTION
ndarray

Sorted coordinates array with same shape as input, with each block

ndarray

sorted clockwise and separated by NaN rows.

RAISES DESCRIPTION
ValueError

If coords array doesn't have shape (N, 3) or plane is invalid.

concat_with_nan_separators staticmethod
concat_with_nan_separators(arrays: list) -> ndarray

Efficiently concatenate numpy arrays with NaN separators.

PARAMETER DESCRIPTION
arrays

List of numpy arrays to concatenate.

TYPE: list

RETURNS DESCRIPTION
ndarray

Concatenated array with NaN separators.

get_area_from_points staticmethod
get_area_from_points(x: ndarray, y: ndarray) -> float

Calculate the area of a closed shape defined by the coordinates in x and y using the shoelace formula. Can handle multiple shapes separated by None values.

extrude_footprint staticmethod
extrude_footprint(x: ndarray, y: ndarray, datum: ndarray, thickness: float) -> Tuple[ndarray, ndarray, ndarray, ndarray]

Extrude a 2D footprint to 3D, handling both single and multi-segment polygons.

PARAMETER DESCRIPTION
x

Array of x coordinates. NaN values indicate segment separators.

TYPE: ndarray

y

Array of y coordinates. NaN values indicate segment separators.

TYPE: ndarray

datum

Datum point for extrusion (shape (3,)).

TYPE: ndarray

thickness

Thickness of the extrusion.

TYPE: float

RETURNS DESCRIPTION
Tuple[ndarray, ndarray, ndarray, ndarray]

Arrays of x, y, z coordinates and side labels, with NaN separators between segments.

get_coordinate_intersection staticmethod
get_coordinate_intersection(coords1: ndarray, coords2: ndarray) -> float

Calculate the intersection area between two sets of coordinates.

PARAMETER DESCRIPTION
coords1

First set of coordinates (N, 2) with columns [x, y].

TYPE: ndarray

coords2

Second set of coordinates (M, 2) with columns [x, y].

TYPE: ndarray

RETURNS DESCRIPTION
float

Intersection area between the two polygons.

RAISES DESCRIPTION
ValueError

If either coordinate set has insufficient valid points for polygon creation.

insert_gaps_with_nans staticmethod
insert_gaps_with_nans(data: ndarray, column_index: int, tolerance_multiplier: float = 2.0) -> ndarray

Insert rows of NaNs when gaps in a specified column exceed a tolerance threshold.

PARAMETER DESCRIPTION
data

Input array with shape (N, M) where N is number of rows and M is number of columns.

TYPE: ndarray

column_index

Index of the column to analyze for gaps (0-based indexing).

TYPE: int

tolerance_multiplier

Multiplier for average gap to determine tolerance threshold. Defaults to 2.0.

TYPE: float DEFAULT: 2.0

RETURNS DESCRIPTION
ndarray

Array with NaN rows inserted where gaps exceed the tolerance.

RAISES DESCRIPTION
ValueError

If column_index is out of bounds for the array.

IndexError

If data array is empty or has insufficient dimensions.

Examples:

>>> data = np.array([[1, 10], [2, 20], [5, 50], [6, 60]])
>>> result = CoordinateMixin.insert_gaps_with_nans(data, column_index=0)
>>> # Will insert NaN row between [2, 20] and [5, 50] if gap of 3 exceeds tolerance
remove_skip_coat_area staticmethod
remove_skip_coat_area(x_coords: ndarray, y_coords: ndarray, weld_tab_positions: ndarray, skip_coat_width: float) -> Tuple[ndarray, ndarray]

Remove skip coat areas around weld tab positions from coordinates.

PARAMETER DESCRIPTION
x_coords

Array of x coordinates defining the boundary.

TYPE: ndarray

y_coords

Array of y coordinates defining the boundary.

TYPE: ndarray

weld_tab_positions

Array of x positions where weld tabs are located.

TYPE: ndarray

skip_coat_width

Width of the skip coat area around each weld tab.

TYPE: float

RETURNS DESCRIPTION
Tuple[ndarray, ndarray]

Modified x and y coordinate arrays with np.nan separators between segments.


Data

Classes

DataMixin

A mixin class providing data processing and validation utilities. Provides methods for monotonicity enforcement and nested breakdown aggregation.

Methods:
enforce_monotonicity staticmethod
enforce_monotonicity(array: ndarray) -> ndarray

Enforces a monotonic version of the input array. If the array is not monotonic, it is smoothed using cumulative max/min.

sum_breakdowns staticmethod
sum_breakdowns(components, breakdown_type: str)

Aggregate breakdown dictionaries across multiple components. If a component doesn't have the specified breakdown, use its fallback attribute instead.

PARAMETER DESCRIPTION
components

List of component objects.

breakdown_type

Type of breakdown to aggregate ('mass', 'cost', etc.).

TYPE: str

RETURNS DESCRIPTION

Aggregated breakdown dictionary with summed values maintaining structure,

or simple float sum if no components have the specified breakdown.


DateTime

steer_core/Mixins/DateTime.py

Lightweight, dependency-free datetime parsing and validation helpers.

Goal: - Provide shared utilities across STEER repos for parsing user-friendly datetime strings into canonical datetime objects with enforced alignment (hour/day).

Classes

DateTimeMixin

A mixin class to handle datetime parsing, validation, and alignment operations. Provides utilities for converting strings to datetime objects with enforced temporal alignment.

Methods:
str_to_datetime staticmethod
str_to_datetime(value: str, *, fmt: Optional[str] = None) -> datetime

Parse a datetime string using a provided strptime format.

If no format is specified, automatically detects and parses using either the hour format ('%Y-%m-%d-%H') or day format ('%Y-%m-%d').

PARAMETER DESCRIPTION
value

The datetime string to parse.

TYPE: str

fmt

The strptime format string (e.g., '%Y-%m-%d-%H'). If None, automatically tries both DEFAULT_HOUR_FMT and DEFAULT_DAY_FMT.

TYPE: Optional[str] DEFAULT: None

RETURNS DESCRIPTION
datetime

The parsed datetime object.

RAISES DESCRIPTION
TypeError

If value is not a string.

ValueError

If value cannot be parsed with the provided or detected format(s).

Examples:

>>> DateTimeMixin.str_to_datetime('2024-01-15-14')
datetime.datetime(2024, 1, 15, 14, 0, 0)
>>> DateTimeMixin.str_to_datetime('2024-01-15')
datetime.datetime(2024, 1, 15, 0, 0, 0)
datetime_to_str staticmethod
datetime_to_str(dt: datetime, *, fmt: Optional[str] = None) -> str

Format a datetime object into a user-friendly string.

If no format is specified, uses the hour format ('%Y-%m-%d-%H').

PARAMETER DESCRIPTION
dt

The datetime object to format.

TYPE: datetime

fmt

The strftime format string (e.g., '%Y-%m-%d-%H', '%Y-%m-%d'). If None, defaults to DEFAULT_HOUR_FMT.

TYPE: Optional[str] DEFAULT: None

RETURNS DESCRIPTION
str

The formatted datetime string.

RAISES DESCRIPTION
TypeError

If dt is not a datetime object.

Examples:

>>> dt = datetime(2024, 1, 15, 14, 0, 0)
>>> DateTimeMixin.datetime_to_str(dt)
'2024-01-15-14'
shift_years staticmethod
shift_years(dt: datetime, years: int) -> datetime

Shift a datetime by a specified number of years (forward or backward).

Handles the edge case of February 29 (leap day): if the original date is Feb 29 and the target year is not a leap year, the result will be Feb 28.

PARAMETER DESCRIPTION
dt

The datetime object to shift.

TYPE: datetime

years

The number of years to shift (positive to add, negative to subtract).

TYPE: int

RETURNS DESCRIPTION
datetime

A new datetime object with the years shifted.

RAISES DESCRIPTION
TypeError

If dt is not a datetime object or years is not an integer.

Examples:

>>> dt = datetime(2026, 2, 2, 14, 0, 0)
>>> DateTimeMixin.shift_years(dt, 2)
datetime.datetime(2028, 2, 2, 14, 0, 0)
shift_months staticmethod
shift_months(dt: datetime, months: int) -> datetime

Shift a datetime by a specified number of months (forward or backward).

Handles month boundaries intelligently: if the original day doesn't exist in the target month (e.g., Jan 31 + 1 month), the result will be the last valid day of that month (e.g., Feb 28 or Feb 29).

PARAMETER DESCRIPTION
dt

The datetime object to shift.

TYPE: datetime

months

The number of months to shift (positive to add, negative to subtract).

TYPE: int

RETURNS DESCRIPTION
datetime

A new datetime object with the months shifted.

RAISES DESCRIPTION
TypeError

If dt is not a datetime object or months is not an integer.

Examples:

>>> dt = datetime(2026, 2, 2, 14, 0, 0)
>>> DateTimeMixin.shift_months(dt, 2)
datetime.datetime(2026, 4, 2, 14, 0, 0)
validate_end_after_start staticmethod
validate_end_after_start(start: datetime, end: datetime, *, strictly: bool = True) -> None

Validate that end datetime comes after start datetime.

PARAMETER DESCRIPTION
start

The start datetime.

TYPE: datetime

end

The end datetime.

TYPE: datetime

strictly

If True, end must be strictly after start (end > start). If False, end can equal start (end >= start). Default is True.

TYPE: bool DEFAULT: True

RAISES DESCRIPTION
TypeError

If start or end is not a datetime object.

ValueError

If end is not after start.

Examples:

>>> start = datetime(2024, 1, 15, 10, 0, 0)
>>> end = datetime(2024, 1, 15, 14, 0, 0)
>>> DateTimeMixin.validate_end_after_start(start, end)  # OK

Datum

Mixin providing standard datum property interface with mm/m unit conversion.

Classes

DatumMixin

Mixin providing uniform datum coordinate properties.

Expects: - _datum: Tuple[float, float, float] instance attribute (stored in meters) - validate_datum(value) method available (from ValidationMixin)

Provides: - datum property (getter/setter) in millimeters - datum_x, datum_y, datum_z properties (getter/setter)

Setter Customization: - Override with @DatumMixin.datum.setter and add decorators like @calculate_coordinates or @calculate_all_properties as needed - For translation-based updates (e.g., assemblies with computed geometry), use _compute_datum_translation() helper before updating _datum

Examples:

Recalculation pattern (most common)::

@DatumMixin.datum.setter @calculate_coordinates def datum(self, value): self.validate_datum(value) self._datum = tuple(float(v) * MM_TO_M for v in value)

Translation pattern (for complex assemblies):

@DatumMixin.datum.setter
def datum(self, value):
    self.validate_datum(value)
    translation = self._compute_datum_translation(value)
    if translation:
        self._translate_all_components(translation)
    self._datum = tuple(float(v) * MM_TO_M for v in value)
Attributes
datum property writable
datum: Tuple[float, float, float]

Datum position in millimeters.

datum_x property writable
datum_x: float

X-coordinate of datum in millimeters.

datum_y property writable
datum_y: float

Y-coordinate of datum in millimeters.

datum_z property writable
datum_z: float

Z-coordinate of datum in millimeters.


Dunder

Classes

DunderMixin

Functions:


Plotter

Classes

PlotterMixin

Methods:
hex_to_rgb staticmethod
hex_to_rgb(hex_color: str) -> tuple[int, int, int]

Convert a hex colour string (e.g. '#4C78A8') to an (R, G, B) tuple.

rgb_to_hex staticmethod
rgb_to_hex(rgb: tuple[int, int, int]) -> str

Convert an (R, G, B) tuple to a hex colour string.

lighten_color staticmethod
lighten_color(hex_color: str, factor: float) -> str

Lighten hex_color by blending towards white.

PARAMETER DESCRIPTION
hex_color

Hex colour string, e.g. '#4C78A8'.

TYPE: str

factor

Blend factor — 0 returns the original colour, 1 returns white.

TYPE: float

hex_to_rgba staticmethod
hex_to_rgba(hex_color: str, alpha: float = 1.0) -> str

Convert a hex colour string to an rgba() CSS string.

create_component_trace staticmethod
create_component_trace(components: list | object, coord_attr: str, name: str, line_width: float, color_func: Callable, unit_conversion_factor: float, order_clockwise: str | None = None, gl: bool = False) -> Scatter | Scattergl | None

Create a single trace for a component or group of components with NaN separators.

PARAMETER DESCRIPTION
components

Single component or list of components to process.

TYPE: list | object

coord_attr

Attribute path for coordinates (e.g., '_a_side_coating_coordinates').

TYPE: str

name

Name for the trace.

TYPE: str

line_width

Width of the trace line.

TYPE: float

color_func

Function to get color from component.

TYPE: Callable

unit_conversion_factor

Factor to convert coordinates to desired units.

TYPE: float

order_clockwise

Plane for clockwise ordering ('xy', 'xz', 'yz') or None to disable, by default None.

TYPE: str | None DEFAULT: None

gl

Whether to use WebGL rendering.

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
Scatter | Scattergl | None

Plotly scatter trace or None if no valid coordinates.

plot_breakdown_sunburst staticmethod
plot_breakdown_sunburst(breakdown_dict: dict[str, Any], title: str = 'Breakdown', root_label: str = 'Total', unit: str = '', colorway: list[str] = None, sort_siblings: bool = True, textinfo: str = 'label', branch_color_map: dict[str, str] | None = None, label_wrap_width: int = 14, **kwargs) -> Figure

Create a sunburst plot for any generic nested breakdown dictionary.

PARAMETER DESCRIPTION
breakdown_dict

Nested dictionary where values can be either numbers or nested dictionaries. Each nesting level becomes a ring in the sunburst plot.

TYPE: dict[str, Any]

title

Title for the plot. Defaults to "Breakdown".

TYPE: str DEFAULT: 'Breakdown'

root_label

Label for the root node. Defaults to "Total".

TYPE: str DEFAULT: 'Total'

unit

Unit string to display in hover text (e.g., "g", "kg", "%"). Defaults to "".

TYPE: str DEFAULT: ''

colorway

List of colors to use for the inner ring. If None, uses Plotly's default colorway. Defaults to None.

TYPE: list[str] DEFAULT: None

sort_siblings

Sort sibling nodes by descending contribution. Defaults to True.

TYPE: bool DEFAULT: True

textinfo

Text displayed on sunburst segments. Defaults to label only, keeping longer labels readable.

TYPE: str DEFAULT: 'label'

branch_color_map

Optional mapping from label text to a base color. Matching labels and their descendants use the mapped color.

TYPE: dict[str, str] | None DEFAULT: None

label_wrap_width

Wrap labels longer than this many characters onto multiple lines. Set to 0 or None to disable wrapping. Defaults to 14.

TYPE: int DEFAULT: 14

RETURNS DESCRIPTION
Figure

Plotly sunburst figure.

plot_scatter staticmethod
plot_scatter(df: DataFrame, x: str, y: str, hover_name: str = None, custom_data: list[str] | None = None, color: str | None = None, size: str | None = None, size_max: int = 30, template: str = 'presentation', layout_defaults: dict[str, Any] | None = None, **kwargs) -> Figure

Create a styled 2-D scatter plot.

PARAMETER DESCRIPTION
df

DataFrame containing the columns referenced by x, y, etc.

TYPE: DataFrame

x

Column name for the X axis.

TYPE: str

y

Column name for the Y axis.

TYPE: str

hover_name

Column whose values appear as the main hover label.

TYPE: str DEFAULT: None

custom_data

Column names to include in customdata for click handlers.

TYPE: list[str] | None DEFAULT: None

color

Column name for colour grouping.

TYPE: str | None DEFAULT: None

size

Column name for marker-size mapping.

TYPE: str | None DEFAULT: None

size_max

Maximum marker size when size is set.

TYPE: int DEFAULT: 30

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_grouped_scatter staticmethod
plot_grouped_scatter(groups, x_values, y_values, x_label: str = 'X', y_label: str = 'Y', group_label: str = 'Group', palette: list[str] | None = None, template: str = 'presentation', layout_defaults: dict[str, Any] | None = None) -> Figure

Create a scatter plot of group means with std dev error bars.

PARAMETER DESCRIPTION
groups

Parallel list of group labels (one per observation).

x_values

Parallel list of numeric X values.

y_values

Parallel list of numeric Y values.

x_label

Human-readable X-axis label.

TYPE: str DEFAULT: 'X'

y_label

Human-readable Y-axis label.

TYPE: str DEFAULT: 'Y'

group_label

Human-readable label for the grouping variable.

TYPE: str DEFAULT: 'Group'

palette

Hex colour palette. Falls back to DEFAULT_PALETTE.

TYPE: list[str] | None DEFAULT: None

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_scatter_3d staticmethod
plot_scatter_3d(df: DataFrame, x: str, y: str, z: str, hover_name: str = None, custom_data: list[str] | None = None, color: str | None = None, size: str | None = None, size_max: int = 30, template: str = 'presentation', layout_defaults: dict[str, Any] | None = None, **kwargs) -> Figure

Create a styled 3-D scatter plot.

PARAMETER DESCRIPTION
df

DataFrame containing the columns referenced by x, y, z, etc.

TYPE: DataFrame

x

Column name for the X axis.

TYPE: str

y

Column name for the Y axis.

TYPE: str

z

Column name for the Z axis.

TYPE: str

hover_name

Column whose values appear as the main hover label.

TYPE: str DEFAULT: None

custom_data

Column names to include in customdata.

TYPE: list[str] | None DEFAULT: None

color

Column name for colour grouping.

TYPE: str | None DEFAULT: None

size

Column name for marker-size mapping.

TYPE: str | None DEFAULT: None

size_max

Maximum marker size when size is set.

TYPE: int DEFAULT: 30

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_grouped_scatter_3d staticmethod
plot_grouped_scatter_3d(groups, x_values, y_values, z_values, x_label: str = 'X', y_label: str = 'Y', z_label: str = 'Z', group_label: str = 'Group', palette: list[str] | None = None, template: str = 'presentation', layout_defaults: dict[str, Any] | None = None) -> Figure

Create a 3-D scatter plot of group means with std dev error bars.

PARAMETER DESCRIPTION
groups

Parallel list of group labels.

x_values

Parallel list of numeric X values.

y_values

Parallel list of numeric Y values.

z_values

Parallel list of numeric Z values.

x_label

Human-readable X-axis label.

TYPE: str DEFAULT: 'X'

y_label

Human-readable Y-axis label.

TYPE: str DEFAULT: 'Y'

z_label

Human-readable Z-axis label.

TYPE: str DEFAULT: 'Z'

group_label

Human-readable label for the grouping variable.

TYPE: str DEFAULT: 'Group'

palette

Hex colour palette. Falls back to DEFAULT_PALETTE.

TYPE: list[str] | None DEFAULT: None

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_bar staticmethod
plot_bar(x, y, custom_data=None, x_label: str = 'X', y_label: str = 'Y', template: str = 'presentation', layout_defaults: dict[str, Any] | None = None, **kwargs) -> Figure

Create a styled bar chart.

PARAMETER DESCRIPTION
x

Values for the X axis.

y

Values for the Y axis.

custom_data

Custom data attached to each bar (for click handlers).

DEFAULT: None

x_label

Human-readable X-axis label.

TYPE: str DEFAULT: 'X'

y_label

Human-readable Y-axis label.

TYPE: str DEFAULT: 'Y'

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_grouped_bar staticmethod
plot_grouped_bar(groups, values, y_label: str = 'Y', group_label: str = 'Group', palette: list[str] | None = None, template: str = 'presentation', layout_defaults: dict[str, Any] | None = None) -> Figure

Create a bar chart showing mean +/- std dev per group.

PARAMETER DESCRIPTION
groups

Parallel list of group labels (one per observation).

values

Parallel list of numeric values (one per observation).

y_label

Human-readable Y-axis label.

TYPE: str DEFAULT: 'Y'

group_label

Human-readable X-axis (group axis) label.

TYPE: str DEFAULT: 'Group'

palette

Hex colour palette. Falls back to DEFAULT_PALETTE.

TYPE: list[str] | None DEFAULT: None

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_histogram staticmethod
plot_histogram(x, x_label: str = 'Value', template: str = 'presentation', layout_defaults: dict[str, Any] | None = None, **kwargs) -> Figure

Create a styled histogram.

PARAMETER DESCRIPTION
x

Values to bin.

x_label

Human-readable axis label.

TYPE: str DEFAULT: 'Value'

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_grouped_histogram staticmethod
plot_grouped_histogram(groups, values, x_label: str = 'Value', palette: list[str] | None = None, template: str = 'presentation', layout_defaults: dict[str, Any] | None = None) -> Figure

Create overlaid histograms, one per group.

PARAMETER DESCRIPTION
groups

Parallel list of group labels.

values

Parallel list of numeric values.

x_label

Human-readable axis label.

TYPE: str DEFAULT: 'Value'

palette

Hex colour palette. Falls back to DEFAULT_PALETTE.

TYPE: list[str] | None DEFAULT: None

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_pdf staticmethod
plot_pdf(values, label: str = 'Value', color_groups: dict[str, list[float]] | None = None, template: str = 'presentation', layout_defaults: dict[str, Any] | None = None) -> Figure

Create a probability-density histogram (one trace per colour group).

PARAMETER DESCRIPTION
values

Values to bin (used when color_groups is None).

label

Human-readable axis label.

TYPE: str DEFAULT: 'Value'

color_groups

Mapping {group_name: [values]} for overlaid per-group traces.

TYPE: dict[str, list[float]] | None DEFAULT: None

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_grouped_pdf staticmethod
plot_grouped_pdf(groups, values, label: str = 'Value', palette: list[str] | None = None, template: str = 'presentation', layout_defaults: dict[str, Any] | None = None) -> Figure

Create overlaid probability-density histograms, one per group.

PARAMETER DESCRIPTION
groups

Parallel list of group labels.

values

Parallel list of numeric values.

label

Human-readable axis label.

TYPE: str DEFAULT: 'Value'

palette

Hex colour palette. Falls back to DEFAULT_PALETTE.

TYPE: list[str] | None DEFAULT: None

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_box staticmethod
plot_box(y, x=None, custom_data=None, y_label: str = 'Y', points: str = 'all', template: str = 'presentation', layout_defaults: dict[str, Any] | None = None, **kwargs) -> Figure

Create a styled box plot.

PARAMETER DESCRIPTION
y

Values for the Y axis.

x

Category values for grouping along the X axis.

DEFAULT: None

custom_data

Custom data attached to each point (for click handlers).

DEFAULT: None

y_label

Human-readable Y-axis label.

TYPE: str DEFAULT: 'Y'

points

One of 'all', 'outliers', 'suspectedoutliers', or False.

TYPE: str DEFAULT: 'all'

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_violin staticmethod
plot_violin(y, x=None, custom_data=None, y_label: str = 'Y', points: str = 'all', box: bool = True, template: str = 'presentation', layout_defaults: dict[str, Any] | None = None, **kwargs) -> Figure

Create a styled violin plot.

PARAMETER DESCRIPTION
y

Values for the Y axis.

x

Category values for grouping along the X axis.

DEFAULT: None

custom_data

Custom data attached to each point.

DEFAULT: None

y_label

Human-readable Y-axis label.

TYPE: str DEFAULT: 'Y'

points

One of 'all', 'outliers', 'suspectedoutliers', or False.

TYPE: str DEFAULT: 'all'

box

Whether to overlay an inner box-plot.

TYPE: bool DEFAULT: True

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_strip staticmethod
plot_strip(y, x=None, hover_name=None, custom_data=None, y_label: str = 'Y', template: str = 'presentation', layout_defaults: dict[str, Any] | None = None, **kwargs) -> Figure

Create a styled strip (jitter) plot.

PARAMETER DESCRIPTION
y

Values for the Y axis.

x

Category values for grouping along the X axis.

DEFAULT: None

hover_name

Values to display as the main hover label.

DEFAULT: None

custom_data

Custom data attached to each point.

DEFAULT: None

y_label

Human-readable Y-axis label.

TYPE: str DEFAULT: 'Y'

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_radar staticmethod
plot_radar(df: DataFrame, axis_labels: list[str], inverted: dict[str, bool] | None = None, color_column: str | None = None, name_column: str = 'name', palette: list[str] | None = None, template: str = 'presentation', layout_defaults: dict[str, Any] | None = None) -> Figure

Create a normalised radar (spider) chart.

Each row in df becomes a Scatterpolar trace. Values are normalised to 0–1 per axis so properties with very different scales are comparable. Per-spoke tick annotations show the original values.

PARAMETER DESCRIPTION
df

Must contain columns named in axis_labels (raw values) and name_column. Optionally contains color_column.

TYPE: DataFrame

axis_labels

Column names in df for the radar axes.

TYPE: list[str]

inverted

{axis_label: True} for axes where lower raw values should appear further from the centre (e.g. cost). Defaults to inverting any axis whose label contains "cost" (case-insensitive).

TYPE: dict[str, bool] | None DEFAULT: None

color_column

Column name for categorical colour grouping.

TYPE: str | None DEFAULT: None

name_column

Column name used as the trace name / hover label.

TYPE: str DEFAULT: 'name'

palette

Hex colour palette. Falls back to DEFAULT_PALETTE.

TYPE: list[str] | None DEFAULT: None

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_grouped_radar staticmethod
plot_grouped_radar(df: DataFrame, axis_labels: list[str], group_column: str, inverted: dict[str, bool] | None = None, palette: list[str] | None = None, template: str = 'presentation', layout_defaults: dict[str, Any] | None = None) -> Figure

Create a normalised radar chart showing group means with std dev bands.

Rows are grouped by group_column; each group becomes a trace showing the per-axis mean. A lighter shaded band shows +/- 1 std dev.

PARAMETER DESCRIPTION
df

Must contain columns named in axis_labels and group_column.

TYPE: DataFrame

axis_labels

Column names in df for the radar axes.

TYPE: list[str]

group_column

Column name used for grouping.

TYPE: str

inverted

{axis_label: True} for axes where lower is better. Defaults to inverting any axis whose label contains "cost".

TYPE: dict[str, bool] | None DEFAULT: None

palette

Hex colour palette. Falls back to DEFAULT_PALETTE.

TYPE: list[str] | None DEFAULT: None

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.

plot_correlation_heatmap staticmethod
plot_correlation_heatmap(df: DataFrame, axis_labels: list[str], template: str = 'presentation', layout_defaults: dict[str, Any] | None = None) -> Figure

Create an annotated Pearson correlation heatmap.

PARAMETER DESCRIPTION
df

DataFrame containing at least axis_labels as numeric columns.

TYPE: DataFrame

axis_labels

Column names to include in the correlation matrix.

TYPE: list[str]

template

Plotly template name.

TYPE: str DEFAULT: 'presentation'

layout_defaults

Additional fig.update_layout overrides applied last.

TYPE: dict[str, Any] | None DEFAULT: None

RETURNS DESCRIPTION
Figure

Plotly figure.


Propagation

Mixin for update propagation through hierarchical object trees.

Classes

PropagationMixin

Mixin providing update propagation through a hierarchical object tree.

This mixin adds two methods: - update(): Triggers the parent's setter for this object (one level up) - propagate_changes(): Triggers parent setters all the way up to root

Each object can have a parent reference. When a child is assigned to a parent, the parent should call child._set_parent(self, 'attribute_name') to establish the link. The attribute name is used during propagation to re-assign the child to the parent via its setter.

Python's cyclic garbage collector handles any circular references.

Serialization Note

The _parent reference is skipped during serialization to avoid circular serialization. Parent references are re-established when objects are reassembled after deserialization (via setters that call _set_parent).

Example Usage:

Change property at any depth:

root.assembly.layout.child.sub_component.thickness = new_value

Option 1: Update current level by triggering parent's setter

root.assembly.layout.child.sub_component.update()

Equivalent to: a.b.c.sub_component = a.b.c.sub_component
Option 2: Propagate changes all the way to root (triggers all parent setters)

root.assembly.layout.child.sub_component.propagate_changes()

Equivalent to re-assigning at each level up to root
Methods:
update
update() -> None

Trigger the parent's setter for this object.

This is equivalent to parent.attr = self, ensuring that all setter logic (validation, coordinate calculation, etc.) is executed.

If this object has no parent, falls back to calling _calculate_all_properties() directly.

Use propagate_changes() to bubble updates all the way to the root.

batch_updates
batch_updates() -> Generator[None, None, None]

Context manager for efficient batch property updates.

Temporarily disables automatic recalculation during property changes, then performs a single recalculation when exiting the context.

Use this when setting multiple properties at once to avoid redundant recalculations that would otherwise occur after each property change.

Examples:

>>> with obj.batch_updates():
...     obj.property_a = value_a
...     obj.property_b = value_b
# Single recalculation happens here
YIELDS DESCRIPTION
None

None

propagate_changes
propagate_changes() -> None

Propagate changes up to root by triggering parent setters.

This method triggers the parent's setter by re-assigning this object to its parent attribute. This ensures any parent setter logic (validation, name modification, coordinate calculation, etc.) is executed during propagation.

The propagation continues recursively until reaching the root.

Note: This does NOT call update() on the current object - that should already have happened via the property setter's @calculate_all_properties decorator when the property was modified.

Use this when you want changes to bubble up automatically. Use update() instead when you need to manually trigger recalculation.

Functions:

propagating_setter

propagating_setter(attr_name: str = None, deepcopy: bool = False)

Decorator for setters that manage parent-child relationships.

This decorator: 1. Clears the old child's parent reference (if replacing with different object) 2. Optionally creates a deep copy of the value (for storing copies) 3. Sets the new child's parent reference with the attribute name

PARAMETER DESCRIPTION
attr_name

The attribute name to use for propagation. If not provided, the decorator will derive it from the setter's name.

TYPE: str DEFAULT: None

deepcopy

If True, creates a deep copy of the value before passing to the setter. Useful when you want to store a copy rather than the original. During propagation (re-assignment of the same stored object), no copy is made to avoid unnecessary duplication.

TYPE: bool DEFAULT: False

Example Usage:

Standard usage (no copy):

@component.setter @calculate_all_properties @propagating_setter() def component(self, component: _Component): self.validate_type(component, _Component, "component") self._component = component

With deepcopy (stores a copy):

@material.setter @calculate_bulk_properties @propagating_setter(deepcopy=True) def material(self, material: Material | None): self.validate_type(material, Material, "material") self._material = material # This is already a copy


Serializer

Classes

SerializerMixin

Methods:
serialize
serialize(compress: bool = True) -> bytes

Serialize object using MessagePack with numpy support.

PARAMETER DESCRIPTION
compress

Whether to compress the serialized data (default: True).

TYPE: bool DEFAULT: True

RETURNS DESCRIPTION
bytes

The serialized byte representation of the object.

deserialize classmethod
deserialize(data: bytes) -> T

Deserialize byte data into an object. Automatically detects and decompresses if needed. Supports both LZ4 (new) and zlib (legacy) compression.

PARAMETER DESCRIPTION
data

The byte data to deserialize.

TYPE: bytes

RETURNS DESCRIPTION
T

Instance of the class.

from_database classmethod
from_database(name: str, table_name: str = None) -> T

Pull object from the database by name.

Subclasses must define a '_table_name' class variable (str or list of str) unless table_name is explicitly provided.

The backend is selected by the OPENCELL_ENV environment variable:

  • development (default) — uses the local SQLite database via steer_opencell_data.DataManager. No network calls, works offline. Requires steer-opencell-data to be installed with database.db.
  • production — uses the REST API via steer_core.Data.DataManager. Requires the API_URL env var pointing to the deployed Lambda endpoint.
PARAMETER DESCRIPTION
name

Name of the object to retrieve.

TYPE: str

table_name

Specific table to search. If provided, '_table_name' is not required. If None, uses class's _table_name.

TYPE: str DEFAULT: None

RETURNS DESCRIPTION
T

Instance of the class.

RAISES DESCRIPTION
NotImplementedError

If the subclass doesn't define '_table_name' and table_name is not provided.

ValueError

If the object name is not found in any of the tables.


Thermodynamics

Thermodynamics mixin providing generic phase equilibrium calculations.

This mixin provides reusable thermodynamic functions that can be composed with material classes.

Classes

ThermodynamicsMixin

Mixin providing generic thermodynamic calculation methods.

Methods:
calculate_antoine_pressure staticmethod
calculate_antoine_pressure(T: float, A: float, B: float, C: float) -> float

Calculate vapor pressure using Antoine equation.

Equation: log10(P) = A - B / (T + C)

PARAMETER DESCRIPTION
T

Temperature (units depend on Antoine coefficients, typically °C or K)

TYPE: float

A, B, C

Antoine coefficients for the substance

RETURNS DESCRIPTION
float

Vapor pressure (units depend on Antoine coefficients, typically mmHg or bar)

calculate_antoine_temperature staticmethod
calculate_antoine_temperature(P: float, A: float, B: float, C: float) -> float

Calculate temperature from vapor pressure using inverse Antoine equation.

PARAMETER DESCRIPTION
P

Vapor pressure (same units as Antoine coefficients)

TYPE: float

A, B, C

Antoine coefficients for the substance

RETURNS DESCRIPTION
float

Temperature (same units as Antoine coefficients)

calculate_ideal_gas_density staticmethod
calculate_ideal_gas_density(P_Pa: float, T_K: float, MW_kg_mol: float) -> float

Calculate ideal gas density using ideal gas law.

PARAMETER DESCRIPTION
P_Pa

Pressure in Pascals

TYPE: float

T_K

Temperature in Kelvin

TYPE: float

MW_kg_mol

Molecular weight in kg/mol

TYPE: float

RETURNS DESCRIPTION
float

Density in kg/m³


TypeChecker

Classes

ValidationMixin

Methods:
validate_plotly_trace staticmethod
validate_plotly_trace(value: object, name: str) -> bool

Check whether value is a Plotly trace object.

PARAMETER DESCRIPTION
value

The value to validate.

TYPE: object

name

The name of the parameter (unused, kept for API compatibility).

TYPE: str

RETURNS DESCRIPTION
bool

True if value is a Plotly trace, False otherwise.

validate_type staticmethod
validate_type(value, expected_type, name: str) -> None

Validate that a value is of the expected type or one of multiple allowed types.

PARAMETER DESCRIPTION
value

The value to validate.

expected_type

A single expected type or an iterable (list/tuple/set) of acceptable types.

name

The name of the parameter for error messages.

TYPE: str

RAISES DESCRIPTION
TypeError

If the value is not an instance of any of the expected types.

Examples:

>>> ValidationMixin.validate_type(5, int, 'count')            # OK
>>> ValidationMixin.validate_type(5, (int, float), 'count')   # OK
>>> ValidationMixin.validate_type('x', (int, float), 'count') # TypeError
>>> ValidationMixin.validate_type([1,2,3], list, 'items')     # OK
>>> ValidationMixin.validate_type([1,2,3], [list, tuple], 'items') # OK
validate_percentage staticmethod
validate_percentage(value: float, name: str) -> None

Validate that a value is a percentage (between 0 and 100).

PARAMETER DESCRIPTION
value

The value to validate.

TYPE: float

name

The name of the parameter for error messages.

TYPE: str

RAISES DESCRIPTION
ValueError

If the value is not a percentage.

validate_fraction staticmethod
validate_fraction(value: float, name: str) -> None

Validate that a value is a fraction (between 0 and 1).

PARAMETER DESCRIPTION
value

The value to validate.

TYPE: float

name

The name of the parameter for error messages.

TYPE: str

RAISES DESCRIPTION
ValueError

If the value is not a fraction.

validate_pandas_dataframe staticmethod
validate_pandas_dataframe(df: DataFrame, name: str, column_names: list | None = None) -> None

Validate that the input is a pandas DataFrame.

PARAMETER DESCRIPTION
df

The DataFrame to validate.

TYPE: DataFrame

name

The name of the DataFrame for error messages.

TYPE: str

RAISES DESCRIPTION
TypeError

If the input is not a pandas DataFrame.

validate_datum staticmethod
validate_datum(datum: ndarray) -> None

Validate the datum point for extrusion.

PARAMETER DESCRIPTION
datum

Datum point for extrusion (shape (3,)).

TYPE: ndarray

RAISES DESCRIPTION
ValueError

If the datum does not have exactly 3 coordinates.

validate_positive_float staticmethod
validate_positive_float(value: float, name: str) -> None

Validate that a value is a positive float.

PARAMETER DESCRIPTION
value

The value to validate.

TYPE: float

name

The name of the parameter for error messages.

TYPE: str

RAISES DESCRIPTION
ValueError

If the value is not a positive float.

validate_positive_int staticmethod
validate_positive_int(value: int, name: str, strictly: bool = True) -> None

Validate that a value is a positive integer.

PARAMETER DESCRIPTION
value

The value to validate.

TYPE: int

name

The name of the parameter for error messages.

TYPE: str

strictly

If True (default), value must be strictly positive (> 0). If False, value must be non-negative (>= 0).

TYPE: bool DEFAULT: True

RAISES DESCRIPTION
TypeError

If the value is not an integer (bool is rejected even though it is a subclass of int).

ValueError

If the integer does not meet the positivity requirement.

Examples:

>>> ValidationMixin.validate_positive_int(5, 'count')              # OK
>>> ValidationMixin.validate_positive_int(0, 'count')              # ValueError (strict mode)
>>> ValidationMixin.validate_positive_int(0, 'count', strictly=False)  # OK (non-strict mode)
>>> ValidationMixin.validate_positive_int(-3, 'count')             # ValueError
>>> ValidationMixin.validate_positive_int(True, 'flag')            # TypeError (bool rejected)
>>> ValidationMixin.validate_positive_int(12_000, 'cycles')        # OK
validate_string staticmethod
validate_string(value: str, name: str) -> None

Validate that a value is a string.

PARAMETER DESCRIPTION
value

The value to validate.

TYPE: str

name

The name of the parameter for error messages.

TYPE: str

RAISES DESCRIPTION
TypeError

If the value is not a string.

validate_two_iterable_of_floats staticmethod
validate_two_iterable_of_floats(value: tuple, name: str) -> None

Validate that a value is a tuple of two iterables.

PARAMETER DESCRIPTION
value

The value to validate.

TYPE: tuple

name

The name of the parameter for error messages.

TYPE: str

RAISES DESCRIPTION
TypeError

If the value is not a tuple of two floats.

validate_positive_float_list staticmethod
validate_positive_float_list(value: list, name: str) -> None

Validate that a value is a list of positive floats.

PARAMETER DESCRIPTION
value

The value to validate.

TYPE: list

name

The name of the parameter for error messages.

TYPE: str

RAISES DESCRIPTION
TypeError

If the value is not a list of positive floats.

validate_enum_string staticmethod
validate_enum_string(value, enum_class: Type[Enum], name: str) -> None

Validate that a string value belongs to an enum class.

PARAMETER DESCRIPTION
value

The string value to validate.

enum_class

The enum class to validate against.

TYPE: Type[Enum]

name

The name of the parameter for error messages.

TYPE: str

RAISES DESCRIPTION
TypeError

If the value is not a string.

ValueError

If the string value is not a valid member of the enum class.

Examples:

>>> from enum import Enum
>>> class AllocationShape(Enum):
...     CIRCLE = 'circle'
...     SQUARE = 'square'
>>> ValidationMixin.validate_enum_string('circle', AllocationShape, 'shape')  # OK
>>> ValidationMixin.validate_enum_string('triangle', AllocationShape, 'shape')  # Raises ValueError
validate_datetime_string staticmethod
validate_datetime_string(value: str, name: str) -> None

Validate that a string is in a valid datetime format.

Accepts either 'YYYY-MM-DD-HH' (hourly) or 'YYYY-MM-DD' (daily) formats.

PARAMETER DESCRIPTION
value

The datetime string to validate.

TYPE: str

name

The name of the parameter for error messages.

TYPE: str

RAISES DESCRIPTION
TypeError

If the value is not a string.

ValueError

If the string is not in a valid datetime format.

Examples:

>>> ValidationMixin.validate_datetime_string('2024-01-15-14', 'start_dt')  # OK
>>> ValidationMixin.validate_datetime_string('2024-01-15', 'start_dt')     # OK
>>> ValidationMixin.validate_datetime_string('2024/01/15', 'start_dt')     # Raises ValueError
validate_number staticmethod
validate_number(value, name: str) -> None

Validate that a value is a numeric amount (int or float, but not bool).

PARAMETER DESCRIPTION
value

The numeric value to validate.

name

The name of the parameter for error messages.

TYPE: str

RAISES DESCRIPTION
TypeError

If the value is a bool or not a numeric type (int or float).

Examples:

>>> ValidationMixin.validate_number(42, 'amount')      # OK
>>> ValidationMixin.validate_number(3.14, 'amount')    # OK
>>> ValidationMixin.validate_number(True, 'amount')    # Raises TypeError
>>> ValidationMixin.validate_number('100', 'amount')   # Raises TypeError
validate_base_binning_frequency staticmethod
validate_base_binning_frequency(value, name: str = 'base_binning_frequency') -> None

Validate that value is an allowed base binning frequency ('hourly' or 'daily').

Parameters

value : Frequency enum or str The value to validate. name : str Parameter name used in the error message.

Raises

ValueError If the value is not 'hourly' or 'daily'.

validate_display_frequency staticmethod
validate_display_frequency(display_freq, base_freq, name: str = 'display_frequency') -> None

Validate that display_freq is equal to or coarser than base_freq.

Parameters

display_freq : Frequency enum The display frequency to validate. base_freq : Frequency enum The base binning frequency. name : str Parameter name used in the error message.

Raises

ValueError If display_freq is finer than base_freq.

validate_base_binning_frequency_not_increased staticmethod
validate_base_binning_frequency_not_increased(current_freq, new_freq, name: str = 'base_binning_frequency') -> None

Validate that new_freq is not finer than current_freq.

Prevents increasing the resolution of an already-set base binning frequency (e.g., daily → hourly), which would fabricate precision that was never there. Going coarser (hourly → daily) is always allowed.

Parameters

current_freq : Frequency enum The currently set base binning frequency. new_freq : Frequency enum The proposed new base binning frequency. name : str Parameter name used in the error message.

Raises

ValueError If new_freq is finer than current_freq.

validate_compounding_frequency staticmethod
validate_compounding_frequency(base_freq, compounding_freq, name: str = 'compounding_frequency') -> None

Validate that base_freq is equal to or finer than compounding_freq.

Parameters

base_freq : Frequency enum The base binning frequency. compounding_freq : Frequency enum The compounding frequency. name : str Parameter name used in the error message.

Raises

ValueError If base_freq is coarser than compounding_freq.