Study design and identification#

Use these objects to declare the observed data, identify a causal quantity, and start estimation. CausalStudy is the main entry point. The protocols support advanced identification extensions.

cleverly.CausalStudy

Validate observed data against an immutable causal-study design.

cleverly.StudyProtocol

Record the scientific protocol that gives a causal question its context.

cleverly.PointTreatment

Declare column roles for a point-treatment study.

cleverly.LongitudinalTreatment

Declare time-ordered roles for a longitudinal study.

cleverly.Repeated

Declare a repeated outcome: one non-absorbing outcome column per time point.

cleverly.TimeToEvent

Declare a baseline treatment with one follow-up time and one event code per unit.

cleverly.LongPanel

Declare a longitudinal study read from a long panel: one row per unit and time.

cleverly.longitudinal.PanelLayout

The long-panel roles a container was built from.

cleverly.longitudinal.LongitudinalData.from_long_panel

Build from a long panel: one row per unit and decision time.

cleverly.longitudinal.LongitudinalData.to_long_panel

Return the long panel this container holds: one row per unit and node.

cleverly.Estimand

Define the public contract for a typed causal question.

cleverly.IdentificationProvider

Convert a causal estimand into an observed-data functional.

cleverly.ExplicitAdjustmentProvider

Identify effects from declared adjustment sets or sequential histories.

cleverly.IdentifiedEffect

Bind an estimand to a functional and its identification assumptions.

cleverly.Provenance

Enough to tell whether two results came from the same place.

LongPanel reads a long panel with one row per unit and decision time. It builds the same trajectory container as LongitudinalData.from_long_panel, and PanelLayout records the roles that the container was built from.

Call CausalStudy(data, design=...), then call identify() or estimate(). An identification provider extends this sequence. It does not waive the identification and evidence requirements.

Pass protocol=StudyProtocol(...) to preserve the scientific context across identification, estimation, summaries, and persistence. Sequence inputs normalize to tuples. The constructor rejects blank text and unmatched treatment strategy and version counts.

StudyProtocol.to_dict() returns the JSON-compatible normalized record. canonical_json supplies its canonical representation, and fingerprint supplies its BLAKE2b digest. The digest identifies the protocol record. It does not replace the separate data and fold fingerprints in Provenance.

Each identification and result summary prints the whole record by default. Pass protocol="fingerprint" to summary() to print only the line with the schema and the fingerprint, for example after you print "\n".join(protocol.summary_lines()) once.

The fingerprint records the protocol. It does not verify it. The package does not check that treatment_strategies names the regimens or arms a result estimates, because the strategies are free text. The typed estimand stores the contrast.

The public objects divide responsibility as follows:

object

responsibility

StudyProtocol

study context and study-specific assumption rationale

PointTreatment, LongitudinalTreatment, LongPanel or TimeToEvent

observed column roles and treatment-time structure

Repeated

a non-absorbing outcome column at every node, passed as outcome= of LongitudinalTreatment

typed estimand

the mathematical contrast and intervention metadata

IdentifiedEffect

the observed-data functional and identification contract

estimation method

learner, targeting, inference, and runtime configuration

The record uses selected target-trial components, ICH E9(R1), and concepts from the literature on treatment versions. It is not a complete target-trial protocol or a claim of ICH estimand compliance.

Trusted point and longitudinal artifacts written before StudyProtocol still load. Their summaries state causal study protocol: absent, and their protocol fingerprint is None.