Skip to content

Commit b0490be

Browse files
AnHeuermannclaude
andcommitted
Filter simulation CSV to comparison signals only
Pass the list of signals to be compared (from comparisonSignals.txt or the reference CSV columns) to run_simulate before solving, so that only the relevant observed variables are written to disk. This avoids serialising thousands of algebraic variables when only a handful are actually verified. compare_with_reference gains a signals keyword that accepts the pre-resolved list, skipping the redundant file/CSV read it would otherwise perform itself. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 29aca16 commit b0490be

3 files changed

Lines changed: 65 additions & 30 deletions

File tree

src/compare.jl

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ end
334334

335335
"""
336336
compare_with_reference(sol, ref_csv_path, model_dir, model;
337-
settings) → (total, pass, skip, diff_csv)
337+
settings, signals) → (total, pass, skip, diff_csv)
338338
339339
Compare a DifferentialEquations / MTK solution against the MAP-LIB reference CSV.
340340
@@ -354,33 +354,42 @@ is written whenever there are failures or skipped signals.
354354
355355
# Keyword arguments
356356
- `settings` — a `CompareSettings` instance controlling tolerances and the
357-
error function. Defaults to the module-level settings returned
358-
by `compare_settings()`. Use `configure_comparison!` to change
359-
the defaults, or pass a local `CompareSettings(...)` here.
357+
error function.
358+
- `signals` — explicit list of signal names to compare. When non-empty,
359+
overrides `comparisonSignals.txt` and the full reference CSV
360+
column list.
360361
"""
361362
function compare_with_reference(
362363
sol,
363364
ref_csv_path::String,
364365
model_dir::String,
365366
model::String;
366367
settings::CompareSettings = _CMP_SETTINGS,
368+
signals::Vector{String} = String[],
367369
)::Tuple{Int,Int,Int,String}
368370

369371
times, ref_data = _read_ref_csv(ref_csv_path)
370372
isempty(times) && return 0, 0, 0, ""
371373

372-
# Determine which signals to compare: prefer comparisonSignals.txt
373-
sig_file = joinpath(dirname(ref_csv_path), "comparisonSignals.txt")
374-
using_sig_file = isfile(sig_file)
375-
signals = if using_sig_file
376-
sigs = filter(s -> lowercase(s) != "time" && !isempty(s), strip.(readlines(sig_file)))
377-
sigs_missing = filter(s -> !haskey(ref_data, s), sigs)
378-
isempty(sigs_missing) || error("Signal(s) listed in comparisonSignals.txt not present in reference CSV: $(join(sigs_missing, ", "))")
379-
sigs
374+
# Determine which signals to compare.
375+
# Prefer the caller-supplied list; fall back to comparisonSignals.txt, then
376+
# all columns in the reference CSV.
377+
signals = if !isempty(signals)
378+
sigs_missing = filter(s -> !haskey(ref_data, s), signals)
379+
isempty(sigs_missing) || error("Signal(s) not present in reference CSV: $(join(sigs_missing, ", "))")
380+
signals
380381
else
381-
filter(k -> lowercase(k) != "time", collect(keys(ref_data)))
382+
sig_file = joinpath(dirname(ref_csv_path), "comparisonSignals.txt")
383+
if isfile(sig_file)
384+
sigs = filter(s -> lowercase(s) != "time" && !isempty(s), strip.(readlines(sig_file)))
385+
sigs_missing = filter(s -> !haskey(ref_data, s), sigs)
386+
isempty(sigs_missing) || error("Signal(s) listed in comparisonSignals.txt not present in reference CSV: $(join(sigs_missing, ", "))")
387+
sigs
388+
else
389+
filter(k -> lowercase(k) != "time", collect(keys(ref_data)))
390+
end
382391
end
383-
n_total = length(signals)
392+
n_total = length(signals)
384393

385394
# ── Build variable accessor map ──────────────────────────────────────────────
386395
# var_access: normalized name → Int (state index) or MTK symbolic (observed).

src/pipeline.jl

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,34 @@ function test_model(omc::OMJulia.OMCSession, model::String, results_root::String
7676
par_ok || return ModelResult(
7777
model, true, exp_t, exp_err, false, par_t, par_err, false, 0.0, "", 0, 0, 0, "")
7878

79+
# Resolve reference CSV and comparison signals early so phase 3 can filter
80+
# the CSV output to only the signals that will actually be verified.
81+
ref_csv = isempty(ref_root) ? nothing : _ref_csv_path(ref_root, model)
82+
cmp_signals = if ref_csv !== nothing
83+
sig_file = joinpath(dirname(ref_csv), "comparisonSignals.txt")
84+
if isfile(sig_file)
85+
String.(filter(s -> lowercase(s) != "time" && !isempty(s), strip.(readlines(sig_file))))
86+
else
87+
_, ref_data = _read_ref_csv(ref_csv)
88+
filter(k -> lowercase(k) != "time", collect(keys(ref_data)))
89+
end
90+
else
91+
String[]
92+
end
93+
7994
# Phase 3 ──────────────────────────────────────────────────────────────────
80-
sim_ok, sim_t, sim_err, sol = run_simulate(ode_prob, model_dir, model; csv_max_size_mb)
95+
sim_ok, sim_t, sim_err, sol = run_simulate(ode_prob, model_dir, model;
96+
csv_max_size_mb, cmp_signals)
8197

8298
# Phase 4 (optional) ───────────────────────────────────────────────────────
8399
cmp_total, cmp_pass, cmp_skip, cmp_csv = 0, 0, 0, ""
84-
if sim_ok && !isempty(ref_root)
85-
ref_csv = _ref_csv_path(ref_root, model)
86-
if ref_csv !== nothing
87-
try
88-
cmp_total, cmp_pass, cmp_skip, cmp_csv =
89-
compare_with_reference(sol, ref_csv, model_dir, model)
90-
catch e
91-
@warn "Reference comparison failed for $model: $(sprint(showerror, e))"
92-
end
100+
if sim_ok && ref_csv !== nothing
101+
try
102+
cmp_total, cmp_pass, cmp_skip, cmp_csv =
103+
compare_with_reference(sol, ref_csv, model_dir, model;
104+
signals = cmp_signals)
105+
catch e
106+
@warn "Reference comparison failed for $model: $(sprint(showerror, e))"
93107
end
94108
end
95109

src/simulate.jl

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,24 @@ import ModelingToolkit
66
import Printf: @sprintf
77

88
"""
9-
run_simulate(ode_prob, model_dir, model; csv_max_size_mb) → (success, time, error, sol)
9+
run_simulate(ode_prob, model_dir, model; cmp_signals, csv_max_size_mb) → (success, time, error, sol)
1010
1111
Solve `ode_prob` with Rodas5P (stiff solver). On success, also writes the
12-
full solution as a CSV file `<Short>_sim.csv` in `model_dir`.
12+
solution as a CSV file `<Short>_sim.csv` in `model_dir`.
1313
Writes a `<model>_sim.log` file in `model_dir`.
1414
Returns `nothing` as the fourth element on failure.
1515
16-
CSV files larger than `csv_max_size_mb` MiB are deleted and replaced with a
16+
When `cmp_signals` is non-empty, only observed variables whose names appear in
17+
that list are written to the CSV, keeping file sizes small when only a subset
18+
of signals will be compared.
19+
20+
CSV files larger than `csv_max_size_mb` MiB are replaced with a
1721
`<Short>_sim.csv.toobig` marker so that the report can note the omission.
1822
"""
19-
function run_simulate(ode_prob, model_dir::String, model::String;
20-
csv_max_size_mb::Int = CSV_MAX_SIZE_MB)::Tuple{Bool,Float64,String,Any}
23+
function run_simulate(ode_prob, model_dir::String,
24+
model::String;
25+
cmp_signals ::Vector{String} = String[],
26+
csv_max_size_mb::Int = CSV_MAX_SIZE_MB)::Tuple{Bool,Float64,String,Any}
2127
sim_success = false
2228
sim_time = 0.0
2329
sim_error = ""
@@ -67,7 +73,13 @@ function run_simulate(ode_prob, model_dir::String, model::String;
6773
sys = sol.prob.f.sys
6874
vars = ModelingToolkit.unknowns(sys)
6975
obs_eqs = ModelingToolkit.observed(sys)
70-
obs_syms = [eq.lhs for eq in obs_eqs]
76+
# Only save observed variables that appear in cmp_signals.
77+
# This avoids writing thousands of algebraic variables to disk when
78+
# only a handful are actually verified during comparison.
79+
norm_cmp = Set(_normalize_var(s) for s in cmp_signals)
80+
obs_eqs_filtered = isempty(norm_cmp) ? obs_eqs :
81+
filter(eq -> _normalize_var(string(eq.lhs)) in norm_cmp, obs_eqs)
82+
obs_syms = [eq.lhs for eq in obs_eqs_filtered]
7183
col_names = vcat(
7284
[_clean_var_name(string(v)) for v in vars],
7385
[_clean_var_name(string(s)) for s in obs_syms],

0 commit comments

Comments
 (0)