Skip to content

Commit bc18684

Browse files
Parameterize plot_strength_curve with unit_system
Accept optional unit_system parameter (defaults to DEFAULT_UNIT_SYSTEM). When METRIC, scales y-axis values by PSI_TO_MPA and adjusts ylim/tick locators for MPa display. Add test_metric_unit_system and test_imperial_unit_system to verify correct y-axis labels.
1 parent 3894dec commit bc18684

2 files changed

Lines changed: 44 additions & 9 deletions

File tree

boxcrete/plotting.py

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import matplotlib.pyplot as plt
1515
import torch
1616
from botorch.models import SingleTaskGP
17+
from boxcrete.units import DEFAULT_UNIT_SYSTEM, PSI_TO_MPA, UnitSystem, strength_label
1718
from linear_operator.utils.cholesky import psd_safe_cholesky
1819
from matplotlib.ticker import MultipleLocator
1920
from torch import Tensor
@@ -34,11 +35,12 @@ def plot_strength_curve(
3435
num_t: int = 1024,
3536
nsigma: int = 2,
3637
xlim: tuple[float, float] = (0, 28),
37-
ylim: tuple[float, float] = (-500, 16000),
38+
ylim: tuple[float, float] | None = None,
3839
figsize: tuple[float, float] = (4, 4),
3940
dpi: int = 600,
4041
create_fig: bool = True,
4142
colors: list[str] | None = None,
43+
unit_system: UnitSystem | None = None,
4244
) -> plt.Figure:
4345
"""Plots predicted compressive strength curves as a function of curing time.
4446
@@ -62,16 +64,24 @@ def plot_strength_curve(
6264
num_t: Number of time points to evaluate.
6365
nsigma: Number of standard deviations for the uncertainty band.
6466
xlim: X-axis limits (days).
65-
ylim: Y-axis limits (strength in psi).
67+
ylim: Y-axis limits. Defaults to (-500, 16000) for psi or
68+
(-3.5, 110) for MPa.
6669
figsize: Figure size in inches (width, height).
6770
dpi: Figure resolution.
6871
create_fig: Whether to create a new figure or plot on the current axes.
6972
colors: Optional list of colors for each composition. If None, uses
7073
matplotlib's Tableau color cycle.
74+
unit_system: Unit system for the y-axis. If None, uses
75+
``DEFAULT_UNIT_SYSTEM``.
7176
7277
Returns:
7378
The matplotlib Figure object containing the plot.
7479
"""
80+
if unit_system is None:
81+
unit_system = DEFAULT_UNIT_SYSTEM
82+
scale = PSI_TO_MPA if unit_system == UnitSystem.METRIC else 1.0
83+
if ylim is None:
84+
ylim = (-3.5, 110.0) if unit_system == UnitSystem.METRIC else (-500, 16000)
7585
if compositions.dim() == 1:
7686
compositions = compositions.unsqueeze(0)
7787

@@ -95,20 +105,26 @@ def plot_strength_curve(
95105
curve_std = curve_post.variance.sqrt().detach().squeeze()
96106

97107
color = tableau[i % len(tableau)]
98-
plt.plot(plot_times, curve_mean, color=color)
108+
plt.plot(plot_times, curve_mean * scale, color=color)
99109

100110
if plot_uncertainties:
101111
plt.fill_between(
102112
plot_times,
103-
curve_mean - nsigma * curve_std,
104-
curve_mean + nsigma * curve_std,
113+
(curve_mean - nsigma * curve_std) * scale,
114+
(curve_mean + nsigma * curve_std) * scale,
105115
alpha=0.2,
106116
label="Predicted" if i == 0 else None,
107117
color=color,
108118
)
109119

110120
if observed_data is not None and observed_times is not None:
111-
plt.plot(observed_times, observed_data, "o", label="Observations", c=color)
121+
plt.plot(
122+
observed_times,
123+
observed_data * scale,
124+
"o",
125+
label="Observations",
126+
c=color,
127+
)
112128
plt.legend()
113129

114130
# Configure axes (once, after all curves are plotted)
@@ -126,9 +142,10 @@ def plot_strength_curve(
126142
plt.xlim(xlim)
127143
plt.ylim(ylim)
128144
ax.set_xlabel("Curing Age (days)", fontsize=9)
129-
ax.set_ylabel("Compressive Strength (psi)", fontsize=9)
130-
ax.yaxis.set_major_locator(MultipleLocator(4000))
131-
ax.yaxis.set_minor_locator(MultipleLocator(2000))
145+
ax.set_ylabel(f"Compressive Strength ({strength_label(unit_system)})", fontsize=9)
146+
major_tick = 20 if unit_system == UnitSystem.METRIC else 4000
147+
ax.yaxis.set_major_locator(MultipleLocator(major_tick))
148+
ax.yaxis.set_minor_locator(MultipleLocator(major_tick / 2))
132149
for spine in ax.spines.values():
133150
spine.set_linewidth(1)
134151
ax.tick_params(which="major", width=1, length=8)

test/test_plotting.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,24 @@ def test_multiple_compositions_custom_colors(self):
9292
)
9393
self.assertEqual(self.model.strength_model.posterior.call_count, 3)
9494

95+
def test_metric_unit_system(self):
96+
from boxcrete.units import UnitSystem
97+
98+
fig = plot_strength_curve(
99+
self.model, self.compositions, unit_system=UnitSystem.METRIC, **_FAST
100+
)
101+
ax = fig.axes[0]
102+
self.assertIn("MPa", ax.get_ylabel())
103+
104+
def test_imperial_unit_system(self):
105+
from boxcrete.units import UnitSystem
106+
107+
fig = plot_strength_curve(
108+
self.model, self.compositions, unit_system=UnitSystem.IMPERIAL, **_FAST
109+
)
110+
ax = fig.axes[0]
111+
self.assertIn("psi", ax.get_ylabel())
112+
95113

96114
class TestPlotCalibration(unittest.TestCase):
97115
"""Tests for the plot_calibration function."""

0 commit comments

Comments
 (0)