From 4c5c0bac2caedc51f504363ff3979719171d5273 Mon Sep 17 00:00:00 2001 From: Arthur Koucher Date: Mon, 18 May 2026 16:23:30 -0300 Subject: [PATCH 1/2] fix segment-based RC regression score computation Signed-off-by: Arthur Koucher --- flow/util/correlateRC.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/flow/util/correlateRC.py b/flow/util/correlateRC.py index 65702ee102..2bc9052ebd 100755 --- a/flow/util/correlateRC.py +++ b/flow/util/correlateRC.py @@ -18,6 +18,22 @@ LAYER_HEADER_RE = re.compile("^([^\\(]+)\\(([^\\)]+)\\)$") +# Helper functions +# ============================================================================= + + +# sklearn's default baseline model for scoring the fit i.e., measuring R² is +# "predict the mean" which is not the proper model for our regressions since +# both R and C are through-origin fits - the R² computation doesn't behave +# well for var(y) ≈ 0 - so we compute R² manually with a "predict zero" +# baseline model. +def compute_through_origin_fit_score(model, inputs, observed): + sum_squared_observed = (observed**2).sum() + if sum_squared_observed == 0: + raise ValueError("Cannot score fit: all observed values are zero.") + return 1.0 - ((observed - model.predict(inputs)) ** 2).sum() / sum_squared_observed + + # Parse and validate arguments # ============================================================================= @@ -410,8 +426,8 @@ def generic_rc_fit(type_sieve): resistances, capacitances_ff, ) in layer_models.items(): - r_sq_res = res_model.score(lengths, resistances) - r_sq_cap = cap_model.score(lengths, capacitances_ff) + r_sq_res = compute_through_origin_fit_score(res_model, lengths, resistances) + r_sq_cap = compute_through_origin_fit_score(cap_model, lengths, capacitances_ff) print("{:<12s} | {:>8.4f} | {:>8.4f}".format(layer_name, r_sq_res, r_sq_cap)) print("-" * 34) print("") From f996a665450052151cfdf201d1e6fb13fef20aff Mon Sep 17 00:00:00 2001 From: Arthur Koucher Date: Mon, 18 May 2026 16:57:40 -0300 Subject: [PATCH 2/2] handle empty layers with 'No data' fit score Signed-off-by: Arthur Koucher --- flow/util/correlateRC.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/flow/util/correlateRC.py b/flow/util/correlateRC.py index 2bc9052ebd..b8d75922ac 100755 --- a/flow/util/correlateRC.py +++ b/flow/util/correlateRC.py @@ -30,8 +30,9 @@ def compute_through_origin_fit_score(model, inputs, observed): sum_squared_observed = (observed**2).sum() if sum_squared_observed == 0: - raise ValueError("Cannot score fit: all observed values are zero.") - return 1.0 - ((observed - model.predict(inputs)) ** 2).sum() / sum_squared_observed + return "No data" + score = 1.0 - ((observed - model.predict(inputs)) ** 2).sum() / sum_squared_observed + return f"{score:.4f}" # Parse and validate arguments @@ -428,7 +429,7 @@ def generic_rc_fit(type_sieve): ) in layer_models.items(): r_sq_res = compute_through_origin_fit_score(res_model, lengths, resistances) r_sq_cap = compute_through_origin_fit_score(cap_model, lengths, capacitances_ff) - print("{:<12s} | {:>8.4f} | {:>8.4f}".format(layer_name, r_sq_res, r_sq_cap)) + print("{:<12s} | {:>8s} | {:>8s}".format(layer_name, r_sq_res, r_sq_cap)) print("-" * 34) print("")