Some checks failed
CI / lint (push) Has been cancelled
CI / test (macos-latest, 3.10) (push) Has been cancelled
CI / test (macos-latest, 3.11) (push) Has been cancelled
CI / test (macos-latest, 3.12) (push) Has been cancelled
CI / test (ubuntu-latest, 3.10) (push) Has been cancelled
CI / test (ubuntu-latest, 3.11) (push) Has been cancelled
CI / test (ubuntu-latest, 3.12) (push) Has been cancelled
CI / test (windows-latest, 3.10) (push) Has been cancelled
CI / test (windows-latest, 3.11) (push) Has been cancelled
CI / test (windows-latest, 3.12) (push) Has been cancelled
- core/units: two dominant systems (Metric m/kN, Imperial ft/kip) with display conversion helpers, legacy 4-system migration in ProjectMeta - dialogs/docks: unit-aware material, section, case, load, grid and results labels; diagram renderer unit labels; render controls update - docs: add consistent_units.md; regen examples/*.osmodel artifacts - tests: update persistence/phase8/project/unit-labels for new systems
105 lines
3.9 KiB
Python
105 lines
3.9 KiB
Python
"""Pushover curve axis labels must follow the project's unit system."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import numpy as np
|
|
import pytest
|
|
|
|
pytest.importorskip("PySide6")
|
|
|
|
from otko.core import UnitSystem # noqa: E402
|
|
from otko.services.results import PushoverResults # noqa: E402
|
|
from otko.views.docks.pushover_curve import ( # noqa: E402
|
|
PushoverCurveView,
|
|
_is_rotation_dof,
|
|
)
|
|
|
|
|
|
def _pushover(control_dof: int = 1) -> PushoverResults:
|
|
return PushoverResults(
|
|
case_id=1, case_name="tst", n_steps=5,
|
|
control_node=2, control_dof=control_dof,
|
|
control_disp=np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0]),
|
|
base_shear=np.array([0.0, 100.0, 200.0, 300.0, 400.0, 500.0]),
|
|
)
|
|
|
|
|
|
def test_is_rotation_dof_ndf3() -> None:
|
|
"""In a 2D/ndf=3 model, only DOF 3 is rotational."""
|
|
assert _is_rotation_dof(1, ndf=3) is False
|
|
assert _is_rotation_dof(2, ndf=3) is False
|
|
assert _is_rotation_dof(3, ndf=3) is True
|
|
|
|
|
|
def test_is_rotation_dof_ndf6() -> None:
|
|
"""In a 3D/ndf=6 model, DOFs 4, 5, 6 are rotational."""
|
|
assert _is_rotation_dof(1, ndf=6) is False
|
|
assert _is_rotation_dof(3, ndf=6) is False # Uz in 3D
|
|
assert _is_rotation_dof(4, ndf=6) is True # Rx
|
|
assert _is_rotation_dof(5, ndf=6) is True # Ry
|
|
assert _is_rotation_dof(6, ndf=6) is True # Rz
|
|
|
|
|
|
@pytest.mark.gui
|
|
def test_si_translation_labels(qtbot) -> None: # type: ignore[no-untyped-def]
|
|
v = PushoverCurveView(units=UnitSystem.METRIC, ndf=6)
|
|
qtbot.addWidget(v)
|
|
v.set_results(_pushover(control_dof=1))
|
|
assert "m" in v._plot.getAxis("bottom").labelText
|
|
assert "Displacement" in v._plot.getAxis("bottom").labelText
|
|
assert "N" in v._plot.getAxis("left").labelText
|
|
assert "Base shear" in v._plot.getAxis("left").labelText
|
|
|
|
|
|
@pytest.mark.gui
|
|
def test_si_rotation_labels_show_curvature_and_moment(qtbot) -> None: # type: ignore[no-untyped-def]
|
|
v = PushoverCurveView(units=UnitSystem.METRIC, ndf=3)
|
|
qtbot.addWidget(v)
|
|
v.set_results(_pushover(control_dof=3))
|
|
assert "1/m" in v._plot.getAxis("bottom").labelText
|
|
assert "Curvature" in v._plot.getAxis("bottom").labelText
|
|
assert "N·m" in v._plot.getAxis("left").labelText
|
|
assert "Moment" in v._plot.getAxis("left").labelText
|
|
|
|
|
|
@pytest.mark.gui
|
|
def test_us_in_kip_rotation_labels(qtbot) -> None: # type: ignore[no-untyped-def]
|
|
"""kip-in Moment-Curvature project must NOT show cm / kN anywhere."""
|
|
v = PushoverCurveView(units=UnitSystem.IMPERIAL, ndf=3)
|
|
qtbot.addWidget(v)
|
|
v.set_results(_pushover(control_dof=3))
|
|
x_label = v._plot.getAxis("bottom").labelText
|
|
y_label = v._plot.getAxis("left").labelText
|
|
assert "1/in" in x_label
|
|
assert "kip·in" in y_label
|
|
assert "cm" not in x_label
|
|
assert "kN" not in y_label
|
|
|
|
|
|
@pytest.mark.gui
|
|
def test_us_in_kip_translation_labels(qtbot) -> None: # type: ignore[no-untyped-def]
|
|
v = PushoverCurveView(units=UnitSystem.IMPERIAL, ndf=3)
|
|
qtbot.addWidget(v)
|
|
v.set_results(_pushover(control_dof=1))
|
|
assert "in" in v._plot.getAxis("bottom").labelText
|
|
assert "kip" in v._plot.getAxis("left").labelText
|
|
|
|
|
|
@pytest.mark.gui
|
|
def test_no_auto_scaling_applied_to_values(qtbot) -> None: # type: ignore[no-untyped-def]
|
|
"""Regression: earlier versions divided base_shear by 1000 to
|
|
display kN. The values must now be drawn exactly as stored so
|
|
kip-in users don't see nonsense scaling."""
|
|
v = PushoverCurveView(units=UnitSystem.IMPERIAL, ndf=3)
|
|
qtbot.addWidget(v)
|
|
r = _pushover(control_dof=3)
|
|
v.set_results(r)
|
|
# Take the single line item that was added; the item's data
|
|
# should match the input arrays point-for-point.
|
|
items = [it for it in v._plot.listDataItems()
|
|
if hasattr(it, "getData")]
|
|
assert items, "Pushover curve has no plot items"
|
|
xs, ys = items[0].getData()
|
|
# The first line item is the actual data (reference line is second).
|
|
np.testing.assert_allclose(xs, r.control_disp)
|
|
np.testing.assert_allclose(ys, r.base_shear)
|