Skip to main content

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

vcti_measure-1.0.0.tar.gz (79.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vcti_measure-1.0.0-py3-none-any.whl (53.4 kB view details)

Uploaded Python 3

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

Hashes for vcti_measure-1.0.0.tar.gz
Algorithm Hash digest
SHA256 a80a57e7c135595e58e2ec5f4b3d672ed67414738a57e304298590e21228358b
MD5 4b0648b8157e29efe12766a91a44b947
BLAKE2b-256 441e0fe43cba0352f66b174cdf7dafd43f2845bd5c1507108821348e1d4ac8ac

See more details on using hashes here.

Provenance

The following attestation bundles were made for vcti_measure-1.0.0.tar.gz:

Publisher: release.yml on vcollab/vcti-python-measure

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for vcti_measure-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 27e124b71f83a9f057e393176d944207025d91a84e55b9d69814ea5bb4c971a1
MD5 9659337f3b8c35934a103bd9e9b756d7
BLAKE2b-256 72c1afc9e1af4048d790d9000250329505d4bee365a07ca94d5bf32d16c8d542

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.1.0

2 files

1.0.1

2 files

This release

1.0.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page