Skip to content

Expand calibration into a first-class subsystem - #16

Merged
DiogoRibeiro7 merged 4 commits into
mainfrom
feat/calibration-framework
Aug 11, 2026
Merged

Expand calibration into a first-class subsystem#16
DiogoRibeiro7 merged 4 commits into
mainfrom
feat/calibration-framework

Conversation

@DiogoRibeiro7

@DiogoRibeiro7 DiogoRibeiro7 commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Makes calibration recordable, replayable and inspectable, and adds the method the direct transformation cannot express.

calibration.py becomes a package (_direct, _spec, _diagnostics). setqca.calibration and every existing import keep working — 478 tests passed unchanged through the move.

Specifications

spec = direct_spec("innovation", full_out=20, crossover=50, full_in=80,
                   note="OECD reporting threshold; see section 3.2")
result = calibrate(raw, spec)     # values + spec + diagnostics together
spec.to_json(); CalibrationSpec.from_json(text)

Four methods: direct, crisp, indirect and identity. Specs are validated when written, not when they eventually meet data, so badly ordered anchors raise at the point the mistake is made. The note survives serialisation, because the reason for a calibration is part of it.

Indirect calibration takes an explicit monotone mapping, for shapes the three-anchor form cannot express — a plateau, a step, an asymmetric ramp. Non-monotone mappings are rejected: a calibration that reverses direction is a different concept, not a calibration.

Diagnostics

Five ways a calibration can be arithmetically valid and analytically useless:

Warning Why
exactly 0.5 truth-table corner undefined — the only one that makes a vector unusable
pile-up near the crossover small anchor changes move cases between corners
compression to the extremes effectively crisp; the fuzzy detail is gone
low variance the condition carries little information
never present / never absent cannot discriminate

Reported, not enforced. diagnose_frame gives one row per condition.

Quantile helpers that refuse to be a calibration

suggest_anchors reports quantiles with the caveat attached to the returned object, and nothing in the package will apply them for you. A set defined by its own distribution cannot support a claim about set membership: if the crossover is the sample median, "more in than out" means "above average for these cases", which changes when you add a case and says nothing about the concept.

478 tests at 100% coverage; mypy strict and docs build clean.


Summary by cubic

Elevates calibration to a first-class subsystem with reproducible specs, diagnostics, and a new indirect method, while keeping existing imports working. Adds JSON-serializable CalibrationSpec and a calibrate entrypoint that returns values, spec, and diagnostics together.

  • New Features

    • CalibrationSpec for direct, crisp, indirect, and identity; validated on write; to_json/from_json; keeps note.
    • calibrate(values, spec) returns CalibrationResult with values, spec, and diagnostics; to_frame() helper.
    • Indirect calibration via explicit monotone mappings; rejects non-monotone shapes.
    • Diagnostics: diagnose_calibration and diagnose_frame flag crossover ties, pile-up, extreme compression, low variance, and never present/absent.
    • Quantile helper suggest_anchors returns AnchorSuggestion with a caveat; helpers do not apply anchors.
  • Refactors

    • Split calibration.py into setqca.calibration package (_direct, _spec, _diagnostics) and re-export new APIs from the package root.
    • Existing imports and calibrate_direct/calibrate_crisp remain intact; no migration required.

Written for commit d0be0e9. Summary will update on new commits.

Review in cubic

@DiogoRibeiro7
DiogoRibeiro7 merged commit 424257d into main Aug 11, 2026
15 checks passed
@DiogoRibeiro7
DiogoRibeiro7 deleted the feat/calibration-framework branch August 11, 2026 08:46
@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant