Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions spkmc/cli/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,21 @@ def display_result_statistics(result: "SimulationResult") -> None:
Args:
result: SimulationResult to display statistics for
"""
from spkmc.cli.formatting import log_warning

console.print(format_title("Simulation Statistics"))
stats = result.get_statistics()
max_inf_str = f"{stats['peak_infected']:.4f} (at t={stats['peak_time']:.2f})"
final_recovered_str = f"{stats['final_recovered']:.4f}"
console.print(f" {format_param('Peak infected', max_inf_str)}")
console.print(f" {format_param('Final recovered', final_recovered_str)}")

if not result.is_equilibrated:
log_warning(
"R(t) is still changing at the end of the simulation. "
"Results may not reflect equilibrium. Consider increasing --t-max."
)

console.print()


Expand Down
14 changes: 14 additions & 0 deletions spkmc/models/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@ def final_recovered(self) -> float:
return 0.0
return float(self.R_val[-1])

@property
def is_equilibrated(self) -> bool:
"""Check if the simulation reached equilibrium.

Compares the R(t) curve over its final 10% of time steps.
Returns False when R is still changing significantly,
which usually means t_max is too short for the chosen parameters.
"""
if self.is_empty or len(self.R_val) < 10:
return True
n = max(2, len(self.R_val) // 10)
delta = abs(float(self.R_val[-1]) - float(self.R_val[-n]))
return delta < 0.01

@property
def final_susceptible(self) -> float:
"""Get final susceptible proportion. Returns 0.0 for empty results."""
Expand Down
9 changes: 9 additions & 0 deletions spkmc/web/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,15 @@ def result_metric_cards(result_dict: Dict[str, Any]) -> None:
help="Proportion of population that was infected",
)

# Warn if simulation may not have reached equilibrium
if len(R_val) >= 10:
n = max(2, len(R_val) // 10)
if abs(float(R_val[-1]) - float(R_val[-n])) >= 0.01:
st.warning(
"⚠️ R(t) is still changing at the end of the simulation. "
"Results may not reflect equilibrium. Consider increasing t_max."
)


def experiment_status_badge(experiment: Any) -> str:
"""
Expand Down