spacr.regression_summary

spaCR’s own summary of a regression run — one shape for every mode.

WHY THIS EXISTS. regression_results.summary_text relays the statsmodels summary, verbatim and deliberately: the point of asking for the statsmodels summary is to get the statsmodels summary, and a re-implementation would differ from every textbook a reader compares it against. That is correct, and it means the tab has exactly one source — so most of spacr.regression_spec.REGRESSION_TYPES got nothing because statsmodels does not write a summary for them, and inference='nonparametric' got

No summary: this run came back without a fitted model, so there is none to summarise.

which is TRUE AND USELESS. The permutation path is a within-plate marginal test per guide: no design matrix, no coefficient covariance, no statsmodels object to ask. The run still produced results, and those results have properties worth reporting — just not the ones statsmodels prints.

THE CONTRACT IS THE DELIVERABLE, not the statistics. Every field named in CONTRACT is present in every mode, and each one is either COMPUTED or explicitly NOT APPLICABLE WITH A REASON. A blank is not allowed, and neither is a zero standing in for “we did not check” — that is the failure this module exists to prevent, in miniature. SummaryField refuses to be built any other way, so the rule is enforced by the type rather than by review.

A NONPARAMETRIC RUN LISTS ITS ASSUMPTIONS AS “NOT ASSUMED”, NEVER AS BLANKS. That is the POINT of choosing it, and a summary that left them empty would make the safer method look like the less informative one — which is precisely the mistake a reader would then make in a methods section.

NOTHING HERE IS NEW STATISTICS. It is a collector:

  • spacr.trial_metrics.fit_quality(), .residual_diagnostics, .design_diagnostics, .calibration and .control_recovery already read every scalar off the fitted model, cheaply, and are what a sweep row is built from;

  • spacr.regression_qc.residual_normality() is the normality verdict the QC panel draws, so the picture and the prose cannot disagree;

  • spacr.regression_qc.context_from_model() recovers leverage and the standardised residual from a model that kept its own design;

  • spacr.multiple_testing.critical_p_value() is the exact BH threshold;

  • spacr.qt.widgets.sweep_runs.PREFERRED_COLUMNS names what a run is COMPARED by, and COMPARISON_FIELDS maps every one of those columns onto the field that reports it. The columns a run is compared by should be the columns its summary reports; if they disagree, one of them is wrong.

WHERE IT GOES. The run folder, under spacr.ml.SUMMARY_FILENAME — the file spacr.qt.widgets.regression_results.find_summary_file() already reads back, so re-opening a run from disk shows this summary with no GUI change. The statsmodels text, where there is one, is appended VERBATIM at the end rather than replaced.

Classes

RunSummary

Everything spaCR knows about one finished run.

SummaryField

One reported field: a value, or a reason there is none.

SummarySection

One headed block of fields, in contract order.

Functions

build_run_summary(→ RunSummary)

spaCR's own summary of one run, in the same shape for every mode.

format_run_summary(→ str)

Render a RunSummary as the text written to the run folder.

write_run_summary(→ Optional[str])

Write this run's spaCR summary into its own folder, and return the path.

Module Contents

class spacr.regression_summary.RunSummary[source]

Everything spaCR knows about one finished run.

Parameters:
  • sections – the six sections of SECTIONS, in order.

  • warnings – sentences printed ABOVE everything else. The identifiability warning lives here, which is where it already is on the Summary tab and where it has to stay: statsmodels prints a full table of standard errors regardless, and it looks exactly like a summary of a well-posed fit.

  • verbatim – the statsmodels text summary, appended unchanged, or None.

  • verbatim_note – what the verbatim block is, or why there is none.

  • recommendations – evidence-backed changes derived from values in this summary, in display order.

field(name: str) → SummaryField | None[source]

The first field called name in any section, or None.

Parameters:

name – stable field name to search for across sections.

missing() → List[str][source]

Contract names this summary failed to answer, as section.name.

Empty on every well-formed summary. It is the assertion the whole-product test makes, expressed once here so the test says what it means rather than re-deriving the contract.

section(name: str) → SummarySection | None[source]

The section called name, or None.

Parameters:

name – contract section name to look up.

text() → str[source]

The whole summary as it is written to disk.

class spacr.regression_summary.SummaryField[source]

One reported field: a value, or a reason there is none.

A BLANK IS NOT REPRESENTABLE. Exactly one of value and reason may be given, and neither may be empty, so “we did not check” cannot be written as an empty string and a zero cannot stand in for it either. That is the whole failure this module is about, enforced where it cannot be forgotten.

Parameters:
  • name – stable machine name; unique within its section.

  • label – what the printed line calls it.

  • value – the answer, already formatted for a human.

  • reason – why there is no answer, as a sentence.

  • kind – COMPUTED, NOT_APPLICABLE or NOT_ASSUMED. Defaults from which of the two above was given.

Raises:

ValueError – if both or neither are given, or one is blank.

property answered: bool[source]

True when the field carries a number rather than a reason.

property text: str[source]

The right-hand side of the printed line, prefix included.

class spacr.regression_summary.SummarySection[source]

One headed block of fields, in contract order.

Parameters:
  • name – key into CONTRACT.

  • title – the printed heading.

  • fields – the fields, one per name in CONTRACT[name].

get(name: str) → SummaryField | None[source]

The field called name, or None.

Parameters:

name – stable field name to look up in this section.

spacr.regression_summary.build_run_summary(*, model=None, settings=None, coef_df=None, regression_type=None, res_folder=None, fit_designs=None) → RunSummary[source]

spaCR’s own summary of one run, in the same shape for every mode.

THE CONTRACT IS THE RETURN VALUE. Whatever the regression type and whichever inference was used, the result carries every name in CONTRACT and each one is answered — with a number, or with a sentence saying why this mode cannot have one. RunSummary.missing() is empty on every well-formed summary, and a builder that raises is backfilled with the exception rather than allowed to leave a hole: reporting is not worth losing a field over, and a hole is the failure this module exists to prevent.

Parameters:
  • model – the fitted model, or None — which is the ordinary case for the permutation path and for the sklearn-backed penalised fits, not an error.

  • settings – the run’s settings dict.

  • coef_df – the corrected coefficient table the run wrote.

  • regression_type – the family actually fitted, when the caller knows it (regression_type=None is auto-selected during the run, so the settings may still say None).

  • res_folder – the run folder. regression_data.csv supplies prepared input counts; regression_fit_designs.json supplies measured fit counts when no explicit records are provided.

  • fit_designs – optional per-level measured design counts. Missing fit counts are reported as unknown, never inferred from prepared row counts.

Returns:

RunSummary.

spacr.regression_summary.format_run_summary(summary: RunSummary) → str[source]

Render a RunSummary as the text written to the run folder.

THE WARNING GOES FIRST, where the Summary tab already puts it: a rank-deficient fit prints a full table of standard errors regardless, and it looks exactly like a summary of a well-posed one.

Parameters:

summary – what build_run_summary() returned.

Returns:

the whole summary as text.

spacr.regression_summary.write_run_summary(res_folder, *, model=None, settings=None, coef_df=None, regression_type=None, fit_designs=None) → str | None[source]

Write this run’s spaCR summary into its own folder, and return the path.

CALLED ON EVERY RUN, for every supported regression type and both inferences. It writes the file spacr.qt.widgets.regression_results.find_summary_file() already reads back, so a run re-opened from disk shows this summary with no GUI change (the design taught the panel to read the run folder; the design is about there being something worth reading in it).

THE STATSMODELS SUMMARY IS PRESERVED. ols and beta runs have already written the statsmodels text into this same file by the time this is called; it is rendered again from the model where it can be, and otherwise read back off the file, and either way it is appended UNCHANGED at the end rather than replaced. The whole text is built in memory first, so a failure here leaves the existing file exactly as it was.

Parameters:
  • res_folder – the run folder, beside results.csv.

  • model – the fitted model, or None.

  • settings – the run’s settings dict.

  • coef_df – the corrected coefficient table.

  • regression_type – the family actually fitted.

  • fit_designs – optional measured per-level design counts, also saved as regression_fit_designs.json for faithful reopening without a model.

Returns:

the path written, or None when there was no folder to write into.