spacr.regression_summary

Build a summary of a regression run with the same fields for every mode.

regression_results.summary_text relays the statsmodels summary verbatim, so that it matches the statsmodels output a reader compares it against. Statsmodels writes no summary for most of spacr.regression_spec.REGRESSION_TYPES, and a run with inference='nonparametric' has no fitted model, for which that source alone gives only

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

The permutation path is a within-plate marginal test per guide, with no design matrix, no coefficient covariance and no statsmodels object. Its results still have reportable properties, which differ from the ones statsmodels prints.

Every field named in CONTRACT is present in every mode, and each one is either computed or marked not applicable with a reason. Blank values are not allowed, and a zero may not stand in for an unchecked value. SummaryField raises when constructed any other way, so the type enforces the rule.

A nonparametric run lists the parametric assumptions as “not assumed” rather than leaving them blank, because not making those assumptions is the reason to choose the method.

The module computes no new statistics. It collects values from:

  • 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 the columns runs are compared by, and COMPARISON_FIELDS maps every one of those columns onto the summary field that reports it, so the summary reports the same values runs are compared by.

The summary is written to the run folder under spacr.ml.SUMMARY_FILENAME, the file spacr.qt.widgets.regression_results.find_summary_file() reads, so a run re-opened from disk shows this summary. The statsmodels text, where there is one, is appended verbatim at the end.

Classes

RunSummary

Summary of one finished regression run, in contract sections.

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)

Build the summary of one run, with the same fields for every mode.

format_run_summary(→ str)

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

headline(→ List[SummaryField])

Return the headline fields of a summary, one per HEADLINE entry.

model_identity_line(→ str)

Return a compact description of the model used for a figure.

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]

Summary of one finished regression run, in contract sections.

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

  • warnings – sentences printed above everything else, including the identifiability warning, which the Summary tab also shows first: statsmodels prints a full table of standard errors for a rank-deficient fit, and that table looks like the 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 field cannot be constructed. Exactly one of value and reason may be given, and neither may be empty, so an unchecked value cannot be written as an empty string or as a zero.

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.

__post_init__()[source]

Validate that the field carries exactly one of a value and a reason.

Raises:

ValueError – if it has both or neither; if whichever it has is blank; if the kind is unknown; or if a non-computed field carries a value without a reason. An absent kind is inferred from which of the two was given.

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]

Build the summary of one run, with the same fields for every mode.

Whatever the regression type and inference, the result carries every name in CONTRACT, and each one is answered with a value or with a sentence saying why this mode cannot have one. RunSummary.missing() is empty on every well-formed summary. When a section builder raises, its fields are filled with the exception text instead of being left empty.

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.

Warnings are written first, as on the Summary tab: a rank-deficient fit still prints a full table of standard errors, which looks like the summary of a well-posed fit.

Parameters:

summary – what build_run_summary() returned.

Returns:

the whole summary as text.

spacr.regression_summary.headline(summary: RunSummary) → List[SummaryField][source]

Return the headline fields of a summary, one per HEADLINE entry.

Each returned item is the SummaryField object from its section, not a copy or a recomputation, so the headline and the section always show the same value.

spacr.regression_summary.model_identity_line(regression_type, settings=None, model=None, backend=None) → str[source]

Return a compact description of the model used for a figure.

Parameters:
  • regression_type (str or None) – Regression family. When omitted, the value is read from settings.

  • settings (mapping, optional) – Run settings used to resolve the backend and relevant hyperparameters.

  • model (object, optional) – Fitted estimator. A cross-validated alpha_ value is reported when the estimator provides one.

  • backend (str or None, optional) – Explicit backend name, overriding the value in settings.

Returns:

str – Model family, backend, and applicable hyperparameters, or an empty string when the regression family is unknown.

Notes

Related regression families can produce identical coefficients while differing in uncertainty estimates. Displaying the model identity keeps visually similar figures attributable to the fit that generated them.

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() reads, so a run re-opened from disk shows this summary.

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 possible, otherwise read back from the file, and in both cases appended unchanged at the end. The whole text is built in memory first, so a failure here leaves the existing file unchanged.

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.

Nested helpers

_assumptions_section.add(name, value=None, reason=None, kind='')

Append a labelled field to the assumptions section.

spacr/regression_summary.py:1375

_call_section.add(name, value=None, reason=None, kind='')

Append a labelled field to the hit-calling section.

spacr/regression_summary.py:1724

_design_section.add(name, value=None, reason=None, kind='')

Append a labelled field to the fitted-design section.

spacr/regression_summary.py:869

_excluded_section.add(name, value=None, reason=None, kind='')

Append a labelled field to the exclusions section.

spacr/regression_summary.py:1939

_fit_quality_section.add(name, value=None, reason=None, kind='')

Append a labelled field to the fit-quality section.

spacr/regression_summary.py:1091

_fitted_section.add(name, value=None, reason=None, kind='')

Append a labelled field to the fitted-model section.

spacr/regression_summary.py:701