vcti-measure
Domain-agnostic measurement model — stable identities, canonical units, and one self-describing JSON document per run
Declare a quantity by name and the readings it yields. Declare what to measure it on, and what to read the numbers against. This package obtains the readings — or validates the ones you already have — and turns them into one JSON document per run.
It measures whatever can be read: a person's blood pressure, a city's air, a furnace, a piece of executing code. What is worth measuring, and what can measure it, belong to the domain rather than to the model, so this package declares no measurements, provides no instruments and defines no units. It draws nothing either — reports are built from the document, elsewhere.
Installation
pip install vcti-measure
In requirements.txt
vcti-measure>=1.0.0
In pyproject.toml dependencies
dependencies = [
"vcti-measure>=1.0.0",
]
Quick Start
Declare the quantity you want, with the readings it yields and the units they are recorded in:
from vcti.measure.core import FactorDecl, Measurement, MetricDecl
BLOOD_PRESSURE = Measurement(
name="blood-pressure",
summary="Arterial pressure at the upper arm.",
metrics={
"systolic": MetricDecl(unit="mmHg"),
"diastolic": MetricDecl(unit="mmHg"),
},
factors={"arm": FactorDecl(values=("left", "right"), required=True)},
)
Declare what to measure it on. A manifest is data, at module scope, holding no presentation — under a namespace nobody else would choose, so your results never collide with someone else's:
from vcti.measure.core import Axis, Manifest, Study, Target, Unit
MANIFEST = Manifest(
"example.cardiology",
[Study(
"medication-follow-up",
summary="Follow arterial pressure after a medication change.",
subjects={"patient-8841": patient_record(8841)},
axes=[Axis(name="posture", values=("seated", "standing"))],
measurements=[BLOOD_PRESSURE],
targets={"blood-pressure.systolic": Target(at_most=120)},
)],
units=[Unit(name="mmHg")],
)
Run it, saying what the run was taken under:
from vcti.measure.core import ProgressSummary, Registry, run
summary = ProgressSummary(units=MANIFEST.units)
artifact = run(
MANIFEST,
Registry([]), # the instruments this run may use
conditions={"site": {"clinic": "north", "protocol_revision": "3"}},
progress=summary,
)
summary.finish()
document = artifact.model_dump_json(indent=2)
That document is the whole output: the declaration it ran, the units it uses, the conditions, and every observation. Where it goes is yours — this package touches no storage. Rendering it is a separate step, in a separate package.
Nothing above measures anything yet. The registry is empty, so no
instrument provides blood-pressure, and every observation comes back
marked unavailable carrying the reason — which is the designed behaviour,
not a failure. The artifact is still complete and still valid. Register an
instrument that provides the measurement and the same manifest produces
numbers.
Key API surface
Everything below is importable from vcti.measure.core.
| What you are doing | What you use |
|---|---|
| Declaring a quantity | Measurement, MetricDecl, FactorDecl |
| Declaring what to measure it on | Study, Item, Axis, Derivation, Description |
| Reading numbers against something | Target |
| Publishing a set of studies | Manifest, Unit |
| Providing a measurement | Instrument, Reading, Registry, Selection |
| Obtaining readings | run(), ProgressSummary |
| Validating readings you already hold | assemble(), Observation, MetricValue, FactorValue |
| Reading a document back | load_artifact(), validate_artifact() |
| Working with a document | Artifact, Status, json_schema(), format_value() |
| Naming a reading without measuring | ObservationIdentity, MetricIdentity, SeriesIdentity |
| Handling a refusal | MeasureError and its three stages |
An observation carries one of four statuses — measured, unavailable,
failed or skipped — and the last three carry a reason. A declaration is
refused as a ManifestError, a set of observations as an AssemblyError,
and an unreadable or invalid document as an ArtifactError; all three
descend from MeasureError.
The full reference, generated from the source, is published in the unified VCollab documentation.
What this package is not
It compares nothing. What it supplies is what a comparison needs to be possible: a stable name for what was measured, a canonical unit, and a record self-describing enough to be read years later. Which comparison is worth making — against a target, against something measured beside it, along an axis, across runs — belongs to whoever is asking.
A few things worth knowing, each explained in the design document:
- Preparation receives the item handle and the coordinate, never the instrument, and sits outside the measured interval.
- Subjects are followed over time; references exist only to give a subject's number meaning.
- Each measurement is taken separately, with its own preparation and release.
- An attempt that produced nothing still appears, carrying a status and a reason. Nothing silently disappears, because an observation missing from the document is indistinguishable from one nobody asked for.
- Metric names, units, targets and the points a study declines are all in the declaration, so a manifest can be checked with no instrument installed at all.
- Which instrument answered is provenance, never identity, so replacing a device does not orphan the readings it produced.
Dependencies
pydantic. The artifact's contract is defined as pydantic models, so the
JSON Schema published with each format version is generated from the same
definitions the implementation validates against — the two cannot drift.
Documentation
| If you want to… | Read |
|---|---|
| See practical, real-world usage | docs/patterns.md |
| Understand the architecture and design decisions | docs/design.md |
| Navigate and understand the source | docs/source-guide.md |
| Declare a measurement or write an instrument | docs/extending.md |
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vcti_measure-1.0.0.tar.gz.
File metadata
- Download URL: vcti_measure-1.0.0.tar.gz
- Upload date:
- Size: 79.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a80a57e7c135595e58e2ec5f4b3d672ed67414738a57e304298590e21228358b
|
|
| MD5 |
4b0648b8157e29efe12766a91a44b947
|
|
| BLAKE2b-256 |
441e0fe43cba0352f66b174cdf7dafd43f2845bd5c1507108821348e1d4ac8ac
|
Provenance
The following attestation bundles were made for vcti_measure-1.0.0.tar.gz:
Publisher:
release.yml on vcollab/vcti-python-measure
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vcti_measure-1.0.0.tar.gz -
Subject digest:
a80a57e7c135595e58e2ec5f4b3d672ed67414738a57e304298590e21228358b - Sigstore transparency entry: 2691847730
- Sigstore integration time:
-
Permalink:
vcollab/vcti-python-measure@e85a16025eceebf406588e0cc963d013597ae418 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/vcollab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e85a16025eceebf406588e0cc963d013597ae418 -
Trigger Event:
push
-
Statement type:
File details
Details for the file vcti_measure-1.0.0-py3-none-any.whl.
File metadata
- Download URL: vcti_measure-1.0.0-py3-none-any.whl
- Upload date:
- Size: 53.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27e124b71f83a9f057e393176d944207025d91a84e55b9d69814ea5bb4c971a1
|
|
| MD5 |
9659337f3b8c35934a103bd9e9b756d7
|
|
| BLAKE2b-256 |
72c1afc9e1af4048d790d9000250329505d4bee365a07ca94d5bf32d16c8d542
|
Provenance
The following attestation bundles were made for vcti_measure-1.0.0-py3-none-any.whl:
Publisher:
release.yml on vcollab/vcti-python-measure
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vcti_measure-1.0.0-py3-none-any.whl -
Subject digest:
27e124b71f83a9f057e393176d944207025d91a84e55b9d69814ea5bb4c971a1 - Sigstore transparency entry: 2691848161
- Sigstore integration time:
-
Permalink:
vcollab/vcti-python-measure@e85a16025eceebf406588e0cc963d013597ae418 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/vcollab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e85a16025eceebf406588e0cc963d013597ae418 -
Trigger Event:
push
-
Statement type: