Skip to content

Commit

Permalink
refactor: derating calculations (#1419)
Browse files Browse the repository at this point in the history
* refactor: move common functions to derating_utils.py

* test: update and add tests for refactored derating functions

* refactor: implement Sourcery AI recommendations

* test: add and update tests to cover Sourcery AI recommendations
  • Loading branch information
weibullguy authored Oct 15, 2024
1 parent 7226951 commit c609bcf
Show file tree
Hide file tree
Showing 23 changed files with 1,244 additions and 4,447 deletions.
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v5.0.0
hooks:
- id: check-docstring-first
- id: check-merge-conflict
Expand All @@ -11,7 +11,7 @@ repos:
- id: no-commit-to-branch
- id: trailing-whitespace
- repo: https://github.com/psf/black
rev: '24.8.0'
rev: '24.10.0'
hooks:
- id: black
types_or: [python, pyi]
Expand All @@ -29,7 +29,7 @@ repos:
additional_dependencies: [tomli]
args: [--in-place, --config, ./pyproject.toml]
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: 'v0.6.8'
rev: 'v0.6.9'
hooks:
- id: ruff
args: [ --select, "PL", --select, "F", --ignore, "PLR2004", --config, ./pyproject.toml ]
Expand Down
3,684 changes: 0 additions & 3,684 deletions poetry.lock

This file was deleted.

111 changes: 111 additions & 0 deletions src/ramstk/analyses/derating/derating_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# -*- coding: utf-8 -*-
#
# ramstk.analyses.derating.derating_utils.py is part of the RAMSTK Project
#
# All rights reserved.
# Copyright since 2007 Doyle "weibullguy" Rowland doyle.rowland <AT> reliaqual <DOT> com
"""Component Derating Calculations Module Utility Functions."""

# Standard Library Imports
from typing import Tuple


def do_update_overstress_status(
overstress: int, reason: str, result: Tuple[int, str]
) -> Tuple[int, str]:
"""Update overstress and reason based on check results."""
_ostress, _rsn = result
return overstress or _ostress, reason + _rsn


def do_check_current_limit(
current_ratio: float,
current_limit: float,
) -> Tuple[int, str]:
"""Check if the current ratio exceeds the limit.
:param current_ratio:
:param current_limit:
:return: _overstress, _reason
:rtype: tuple
"""
if current_ratio <= current_limit:
return 0, ""

return (
1,
f"Current ratio of {current_ratio} exceeds the allowable limit of "
f"{current_limit}.\n",
)


def do_check_power_limit(
power_ratio: float,
power_limit: float,
) -> Tuple[int, str]:
"""Check if the power ratio exceeds the limit.
:param power_ratio:
:param power_limit:
:return: _overstress, _reason
:rtype: tuple
"""
if power_ratio <= power_limit:
return 0, ""

return (
1,
f"Power ratio of {power_ratio} exceeds the allowable limit of {power_limit}.\n",
)


def do_check_temperature_limit(
actual_temperature: float, max_rated_temperature: float, limit: float
) -> Tuple[int, str]:
"""Check if actual temperature exceeds the specified limit of rated temperature.
:param actual_temperature: Current temperature in degrees Celsius
:param max_rated_temperature: Maximum rated temperature in degrees Celsius
:param limit: Percentage of max rated temperature allowed (0.0 to 1.0)
:return: Tuple of (1 if limit exceeded, 0 otherwise) and status message
"""
if actual_temperature <= (max_rated_temperature - limit):
return 0, ""

if limit < 1.0:
_reason = (
f"Temperature of {actual_temperature}C exceeds the derated maximum "
f"temperature of {max_rated_temperature}C.\n"
)
else:
_reason = (
f"Temperature of {actual_temperature}C exceeds the derated maximum "
f"temperature of {limit}C less than maximum rated temperature of "
f"{max_rated_temperature}C.\n"
)

return (
1,
_reason,
)


def do_check_voltage_limit(
voltage_ratio: float,
voltage_limit: float,
) -> Tuple[int, str]:
"""Check if the voltage ratio exceeds the limit.
:param voltage_ratio:
:param voltage_limit:
:return: _overstress, _reason
:rtype: tuple
"""
if voltage_ratio <= voltage_limit:
return 0, ""

return (
1,
f"Voltage ratio of {voltage_ratio} exceeds the allowable limit of "
f"{voltage_limit}.\n",
)
126 changes: 61 additions & 65 deletions src/ramstk/analyses/derating/models/capacitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@
# ramstk.analyses.derating.models.capacitor.py is part of the RAMSTK Project
#
# All rights reserved.
# Copyright since 2017 Doyle "weibullguy" Rowland doyle.rowland <AT> reliaqual <DOT> com
# Copyright since 2007 Doyle "weibullguy" Rowland doyle.rowland <AT> reliaqual <DOT> com
"""Capacitor derating analysis functions."""

# Standard Library Imports
from typing import Dict, List, Tuple
from typing import Dict, List, Optional, Tuple

# RAMSTK Package Imports
from ramstk.analyses.derating.derating_utils import (
do_check_temperature_limit,
do_check_voltage_limit,
do_update_overstress_status,
)


def do_derating_analysis(
Expand All @@ -31,6 +38,34 @@ def do_derating_analysis(
_overstress: int = 0
_reason: str = ""

_subcategory = _do_resolve_subcategory(
subcategory_id, kwargs.get("specification_id")
)

# Check temperature limits
_overstress, _reason = do_check_temperature_limit(
kwargs["temperature_case"],
kwargs["temperature_rated_max"],
stress_limits[_subcategory]["temperature"][environment_id],
)

# Check voltage limits
_overstress, _reason = do_update_overstress_status(
_overstress,
_reason,
do_check_voltage_limit(
kwargs["voltage_ratio"],
stress_limits[_subcategory]["voltage"][environment_id],
),
)

return _overstress, _reason


def _do_resolve_subcategory(
subcategory_id: int, specification_id: Optional[int]
) -> str:
"""Resolve the capacitor subcategory based on subcategory and specification ID."""
_subcategory = {
1: "paper",
2: "paper",
Expand All @@ -57,66 +92,27 @@ def do_derating_analysis(
17: "piston",
18: "trimmer",
19: "vacuum",
}[subcategory_id]
if isinstance(_subcategory, dict):
_subcategory = _subcategory[kwargs["specification_id"]]

_overstress, _reason = _do_check_temperature_limit(
kwargs["temperature_case"],
kwargs["temperature_rated_max"],
stress_limits[_subcategory]["temperature"][environment_id],
)

_ostress, _rsn = _do_check_voltage_limit(
kwargs["voltage_ratio"],
stress_limits[_subcategory]["voltage"][environment_id],
)
_overstress = _overstress or _ostress
_reason += _rsn

return _overstress, _reason


def _do_check_temperature_limit(
case_temperature: float,
max_rated_temperature: float,
temperature_limit: float,
) -> Tuple[int, str]:
"""Check if the case temperature exceeds the limit.
:param case_temperature:
:param max_rated_temperature:
:param temperature_limit:
:return: _overstress, _reason
:rtype: tuple
"""
if case_temperature <= (max_rated_temperature - temperature_limit):
return 0, ""

return (
1,
f"Case temperature of {case_temperature}C exceeds the derated maximum "
f"temperature of {temperature_limit}C less than maximum rated temperature "
f"of {max_rated_temperature}C.\n",
)


def _do_check_voltage_limit(
voltage_ratio: float,
voltage_limit: float,
) -> Tuple[int, str]:
"""Check if the voltage ratio exceeds the limit.
:param voltage_ratio:
:param voltage_limit:
:return: _overstress, _reason
:rtype: tuple
"""
if voltage_ratio <= voltage_limit:
return 0, ""

return (
1,
f"Voltage ratio of {voltage_ratio} exceeds the allowable limit of "
f"{voltage_limit}.\n",
)
}

# Explicit check for subcategory_id to make sure it's in the dictionary.
if subcategory_id not in _subcategory:
raise KeyError(f"Unknown subcategory_id: {subcategory_id}")

# Fetch the subcategory (can be a string or a dict).
_resolved_subcategory = _subcategory[subcategory_id]

# If the subcategory is a nested dictionary, resolve using specification_id.
if isinstance(_resolved_subcategory, dict):
if specification_id is None:
raise ValueError(
f"Missing specification_id for subcategory_id {subcategory_id}"
)
if specification_id not in _resolved_subcategory:
raise ValueError(
f"Unknown specification_id {specification_id} for subcategory_id"
f" {subcategory_id}"
)
return _resolved_subcategory[specification_id]

# Return the resolved subcategory for non-nested cases.
return _resolved_subcategory
3 changes: 3 additions & 0 deletions src/ramstk/analyses/derating/models/capacitor.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ def _do_check_temperature_limit(
def _do_check_voltage_limit(
voltage_ratio: float, voltage_limit: float
) -> Tuple[int, str]: ...
def _do_resolve_subcategory(
subcategory_id: int, specification_id: Optional[int]
) -> str: ...
30 changes: 9 additions & 21 deletions src/ramstk/analyses/derating/models/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
# Standard Library Imports
from typing import Dict, List, Tuple

# RAMSTK Package Imports
from ramstk.analyses.derating.derating_utils import do_check_current_limit


def do_derating_analysis(
environment_id: int,
Expand All @@ -25,28 +28,13 @@ def do_derating_analysis(
:rtype: tuple :raise: IndexError if an unknown environment ID is passed. :raise:
TypeError if a non-numeric value is passed for the current ratio.
"""
return _do_check_current_limit(
_overstress: int = 0
_reason: str = ""

# Check current limits
_overstress, _reason = do_check_current_limit(
kwargs["current_ratio"],
stress_limits["current"][environment_id],
)


def _do_check_current_limit(
current_ratio: float,
current_limit: float,
) -> Tuple[int, str]:
"""Check if the current ratio exceeds the limit.
:param current_ratio:
:param current_limit:
:return: _overstress, _reason
:rtype: tuple
"""
if current_ratio <= current_limit:
return 0, ""

return (
1,
f"Current ratio of {current_ratio} exceeds the allowable limit of "
f"{current_limit}.\n",
)
return _overstress, _reason
Loading

0 comments on commit c609bcf

Please sign in to comment.