cleverly.longitudinal.LongitudinalResult#

class cleverly.longitudinal.LongitudinalResult(estimates: dict[str, ~cleverly.inference.influence.ParameterEstimate], fits: dict[str, ~cleverly.longitudinal.sequential.RegimenFit], data: ~cleverly.longitudinal.data.LongitudinalData, config: ~cleverly.longitudinal.estimator.LongitudinalConfig, scaler: ~cleverly.utils.bounds.OutcomeScaler, mechanism: ~cleverly.longitudinal.sequential.Mechanism, folds: ~cleverly.learners.crossfit.Folds, provenance: ~cleverly.provenance.Provenance, simultaneous: ~cleverly.inference.multiplier.SimultaneousBands | None = None, parameter_index: dict[str, tuple[str, str | None, int]] | None = None, msm: ~cleverly.longitudinal.msm.RegimenMSM | None = None, msm_fits: tuple[~cleverly.longitudinal.msm.MSMRegimenFit, ...] = (), identified_effect: ~typing.Any = None, method: ~typing.Any = None, parameter_keys: dict[str, ~typing.Any] = <factory>, fitted_method: str = 'tmle', bootstrap: ~cleverly.inference.bootstrap.BootstrapResult | None = None, bootstrap_band: ~cleverly.inference.bootstrap.BootstrapBand | None = None, isotonic_moves: tuple[tuple[str, str | None, int, float, float], ...] = (), initial_hazards: ~cleverly.longitudinal.hazard.InitialHazards | None = None, *, simulation: ~cleverly.longitudinal.gformula.GFormulaReport | None = None, fold_mechanisms: tuple[~cleverly.longitudinal.sdr.FoldMechanism, ...] = (), replay_recipe: ~cleverly.longitudinal.estimator._LongitudinalReplayRecipe)[source]#

Store estimates and fitted artifacts for longitudinal regimens.

Behaves as a mapping from parameter name to ParameterEstimate, so result["ey_regimen[always]"] and for name in result both work.

Parameters:
estimatesdict of str to ParameterEstimate

Estimates keyed by stable parameter alias. Each declares the fit status, which inference_status returns, or a parameter status such as "constant_node_plugin".

fitsdict of str to RegimenFit

Sequential fits by regimen, cause, and horizon.

dataLongitudinalData

Validated time-ordered study data.

configLongitudinalConfig

Normalized sequential-estimator configuration.

scalerOutcomeScaler

Transformation between observed and targeting scales.

mechanismMechanism

Fitted treatment and observation mechanisms.

foldsFolds

Realized outer-fold assignment.

provenanceProvenance

Runtime, dependency, and data fingerprints.

simultaneousSimultaneousBands or None

Joint confidence bands. None on a fit whose status supplies no inference.

parameter_indexdict or None

Structured regimen, cause, and horizon index.

msmRegimenMSM or None

Evaluated working model. Its functions_kind records whether the source design and projection weights passed their declaration checks.

msm_fitstuple of MSMRegimenFit

Projection fits by cause.

identified_effectIdentifiedEffect or None

Causal question and identifying assumptions.

methodEstimationMethod or None

Typed public method configuration.

parameter_keysdict of str to ParameterKey

Structured identities for reported aliases.

fitted_methodstr

Method identity stamped by the estimator.

bootstrapBootstrapResult or None

The full-refit bootstrap draws, when n_bootstrap > 0 was requested.

bootstrap_bandBootstrapBand or None

The studentized bootstrap sup-t band over the estimates that supply inference. None without a bootstrap, with simultaneous=False, or with fewer than two such estimates.

isotonic_movestuple of tuple

The levels an isotonic=True projection moved, as (regimen, cause, horizon, before, after).

initial_hazardsInitialHazards or None

The initial cause-specific hazards of a survival_model="hazard" fit.

fold_mechanismstuple of FoldMechanism

Each outer fold’s own mechanism on a cross-fitted SDR fit, empty otherwise. Keyword-only.

replay_recipeobject

Unfitted recursive learner templates and resolved plans for deterministic refits. Keyword-only.

simulationGFormulaReport or None

On a ParametricGFormula fit, what the forward simulation drew: the draws, the models, the Monte Carlo share of each parameter and the fixed-dose model reliance. None on every other fit. Keyword-only.

Attributes:
assessment_cachedict

Saved diagnostic and sensitivity outputs. Not a constructor argument, so every constructed result owns its own cache. Persistence restores the mapping without the constructor.

inference_statusstr

The inference status of the fit.

See also

cleverly.estimators.TMLEResult

The same contract for a point-treatment fit.

cleverly.RegimeContrast

The estimand a study declares to get this contrast.

cleverly.LongitudinalTreatment

The design that names these nodes.

LongitudinalResult.ratio

The risk ratio or odds ratio of two regimens.

LongitudinalResult.rmst

The restricted mean survival time of a regimen.

Examples

>>> from sklearn.linear_model import LinearRegression, LogisticRegression
>>> from cleverly.datasets import make_longitudinal
>>> from cleverly.longitudinal import LTMLE
>>> frame, _ = make_longitudinal(n=200, seed=0)
>>> result = LTMLE(
...     {"always": 1, "never": 0},
...     n_folds=2,
...     random_state=0,
...     outcome_learner=LinearRegression(),
...     treatment_learner=LogisticRegression(max_iter=1000),
...     censoring_learner=LogisticRegression(max_iter=1000),
... ).fit(
...     frame,
...     outcome="Y",
...     treatment=["A1", "A2"],
...     baseline=["W1", "W2"],
...     time_varying=[[], ["L2"]],
...     censoring=["C1", "C2"],
... )

The regimen means and their contrast are keyed by the labels the regimens were declared under:

>>> sorted(result.estimates)
['ate_regimen[never vs always]', 'ey_regimen[always]', 'ey_regimen[never]']
>>> low, high = result["ey_regimen[always]"].ci
>>> low < high
True

Methods#

LongitudinalResult.assess(*, include_refits: bool = False, include_retargets: bool = False, arguments: Mapping[str, Mapping[str, Any]] | None = None, random_state: int | None = None) → AssessmentReport[source]#

Run the applicable post-fit assessment battery.

Parameters:
include_refitsbool

Run requested operations that refit nuisance models.

include_retargetsbool

Include moderate retargets; cheap E-value retargets run by default.

argumentsmapping or None

Per-operation keyword arguments.

random_stateint or None

Common seed for stochastic refit operations.

Returns:
cleverly.AssessmentReport

Validation, diagnostics, and sensitivity in one report.

See also

LongitudinalResult.validate

Run stored-artifact validation.

cleverly.assessment.DiagnosticsFacade.run_all

Run diagnostics alone.

LongitudinalResult.coefficients(scale: str = 'link') → Any[source]#

A working model’s coefficients, on the link scale or exponentiated.

The same view cleverly.estimators.base.TMLEResult.coefficients() is at one time point, and it means the same things. scale="link" reports \(\hat\beta\) with a Wald interval on the scale the model is linear on; scale="ratio" reports \(e^{\hat\beta}\) with the interval exponentiated from that scale. What the exponential is depends on the link – a risk ratio under "log" and an odds ratio under "logit" – and the intercept is a third thing again, a baseline mean or a baseline odds rather than a ratio of anything, so the scale column names which each row is. An intercept is found by its column being constant one, not by its name.

Refused on an identity-link fit, where \(e^\beta\) of a risk difference is not a quantity, and on a fit with no working model. Nothing is re-estimated.

Parameters:
scale{“link”, “ratio”}

Coefficient scale to report.

Returns:
dataframe

One row per working-model coefficient in the input backend.

LongitudinalResult.contrast(function: Callable[[ndarray[tuple[Any, ...], dtype[float64]]], float], names: Sequence[str], *, name: str | None = None, scale: Literal['level', 'difference', 'ratio', 'fraction'] = 'difference', gradient: Callable[[ndarray[tuple[Any, ...], dtype[float64]]], ndarray[tuple[Any, ...], dtype[float64]]] | None = None, transform: Transform | None = None) → ParameterEstimate[source]#

Return a smooth contrast with joint delta-method inference.

Parameters:
functioncallable()

Smooth scalar function of the selected estimates.

namessequence of str

Aliases passed to function in order.

namestr or None

Alias for the derived estimate.

scalestr

Reported scale of the derived estimate. With transform= it must be "level" or "difference".

gradientcallable() or None

Analytic gradient. None uses central differences.

transformTransform or None

The map the interval and the test are computed on, as for cleverly.estimators.TMLEResult.contrast().

Returns:
ParameterEstimate

Derived estimate. It inherits the inference status of the selected estimates, so on a fit that supplies no inference it reports the same diagnostic and no interval.

LongitudinalResult.covariance(names: Sequence[str] | None = None) → ndarray[tuple[Any, ...], dtype[float64]][source]#

Return joint covariance for selected estimates.

Parameters:
namessequence of str or None

Aliases in output order. None selects all estimates.

Returns:
ndarray

Covariance matrix at the independent observation or cluster level. On a fit whose status supplies no inference, it is the plug-in covariance of the reported curves, a diagnostic.

LongitudinalResult.curve(scale: str | None = None) → Any[source]#

The report as a curve: a row per parameter per horizon.

On a repeated outcome (Repeated) the only scale is "mean": the mean \(E[Y_t^d]\) of each regimen and the difference between regimens at each horizon. A repeated outcome can return to zero, so it has no survival complement. The rest of this description is about a survival fit.

scale="risk" reports what the fit estimated, the cumulative risk \(F(t)\) and the risk difference between regimens at each horizon. scale="survival" reports \(S(t) = 1 - F(t)\) instead. The view column names the requested view; the scale column keeps the vocabulary to_frame() reports, "level" or "difference", which is what separates a level row from a contrast row without reading any name.

A fit that declared two or more causes refuses the survival view, because event-free survival is the complement of the sum of the cause-specific incidences and not the complement of one of them. With a single declared cause that sum is that one incidence, so the complement is event-free survival and the view is reported.

The map from one to the other is not one rule. For a level, \(S = 1 - F\): the estimate is mirrored about a half and so is its interval. For a contrast it is \(S_a - S_b = -(F_a - F_b)\): the estimate is negated and the interval negated and swapped. Applying 1 - x to a risk difference would report 1 - RD, which is not a quantity, with an interval that would look perfectly reasonable – so this branches on scale rather than on the caller getting it right. The standard error is the same either way, both maps being linear with slope of modulus one.

The time column lives here rather than on to_frame(), which keeps the column names a point-treatment fit reports.

On scale="survival" a level row’s estimand is not a key of this result: the complement of risk_regimen[always @ t=2] is reported as survival_regimen[always @ t=2], which the fit never estimated under that name. A contrast row keeps its ate_regimen[...] name, which is a key, the difference being the same parameter up to a sign. The parameter column carries the key either way, so result[row.parameter] is defined for every row of every view and result[row.estimand] is not.

Parameters:
scale{“risk”, “survival”, “mean”} or None

Outcome scale for levels and contrasts. None reads "risk" on a survival fit and "mean" on a repeated outcome.

Returns:
dataframe

One row per regimen, cause, and horizon in the input backend, with these columns.

estimand

The name of the quantity the row reports, under the requested view.

parameter

The key of the estimate the row was derived from, always in result.estimates.

regimen

The regimen of a level, or the "a vs b" contrast string of a difference.

cause

The absorbing cause, on a fit that declared its causes only.

time

The horizon, as an integer node index, or as the grid time \(g_k\) on a fit with a time grid.

support

"supported" or "experimental", the label of the estimate the row reads. support gives its reason.

inference

The inference status of each row, on a fit with a labelled status, shown or withheld, or with a parameter that carries one.

psi, std_err, ci_lower, ci_upper

The estimate, its standard error, and its confidence interval, under the requested view. On a fit whose status supplies no inference the three spread columns are plugin_std_err, plugin_interval_lower and plugin_interval_upper, a diagnostic, as to_frame() names them. On a fit that supplies inference, a row with a parameter status has NaN in the three inferential columns and its diagnostic in the three plug-in columns, which the frame then adds.

scale

"level" or "difference", as to_frame() reports it.

view

"risk", "survival" or "mean", the view the caller requested.

LongitudinalResult.incidence_total() → Any[source]#

Per regimen and horizon, the incidences summed over the causes.

A unit leaves the risk set through exactly one cause or not at all, so the cumulative incidences and the event-free probability exhaust the mass: \(\sum_j F_j(k) + S(k) = 1\). That identity holds of the parameters. It does not hold of these estimates, and the difference is not a bug to fix. Each cause is a separate backward pass – its own regressions, its own fluctuation – so nothing constrains the sum, and a total above one is possible.

It is reported rather than removed, on the same reasoning as simplex_deviation, where a multi-arm mechanism’s row is deliberately not rescaled back onto the simplex. Renormalising would buy a coherent-looking table by moving every cause’s estimate away from the one its own score equation solved, and would hide the thing worth seeing: a total far from one says the causes disagree about how much risk there was, which is a statement about the nuisance fits and not about the parameter.

The total column carries a standard error because the sum is itself a parameter with an influence curve – the sum of the causes’ curves – so excess can be read against it rather than eyeballed. On a fit whose status supplies no inference the column is plugin_std_err, a diagnostic, as to_frame() names the same spread. Each total takes the status of the incidences it sums. On a fit that supplies inference, a total that reads a constant-node incidence has NaN under std_err, its spread under plugin_std_err, and its status in an inference column.

Returns:
dataframe

One row per regimen and horizon, with the incidences summed over causes. The support column holds the label of the combined incidences, and a fit with a labelled status adds the inference column.

LongitudinalResult.psi(name: str | None = None) → float[source]#

Return a point estimate by parameter alias.

Parameters:
namestr or None

Parameter alias. None is allowed only when the fit reported one.

Returns:
float

The point estimate for that parameter.

LongitudinalResult.ratio(numerator: str, denominator: str, *, kind: Literal['rr', 'or'] = 'rr', view: Literal['risk', 'survival'] = 'risk', name: str | None = None) → ParameterEstimate[source]#

The risk ratio or odds ratio of two regimen levels, with log-scale inference.

The ratio of two ey_regimen means, of two risk_regimen risks at one horizon, or of two cif_regimen incidences at one cause and horizon. The interval is computed on the log scale and exponentiated, as lmtp_contrast(type = "rr") and type = "or" in R lmtp 1.5.4 compute it. view="survival" takes the ratio of \(1 - F\) instead of \(F\). The ratio inherits the inference status of its inputs.

Parameters:
numeratorstr

The name of the level in the numerator.

denominatorstr

The name of the level in the denominator.

kind{“rr”, “or”}, default=”rr”

A ratio of the levels, or a ratio of their odds. On an end-of-study fit "or" needs a binary outcome.

view{“risk”, “survival”}, default=”risk”

Whether to take the ratio of the risks or of the survival probabilities.

namestr or None, default=None

The name of the derived estimate. None composes rr_regimen[a vs b @ t=h] from the parameter index when both inputs are levels at one cause and horizon, and rr[<numerator> vs <denominator>] otherwise.

Returns:
ParameterEstimate

The ratio, on the "ratio" scale.

Raises:
CapabilityError

When kind="or" and an end-of-study outcome is not binary.

ValueError

When an input is not a level, when view="survival" is requested of an end-of-study fit or of a fit with two or more causes, or when this fit reports the coefficients of a working model.

See also

cleverly.inference.ParameterEstimate.wald_test

Test the ratio at a null.

Examples

>>> from sklearn.linear_model import LinearRegression, LogisticRegression
>>> from cleverly.datasets import make_longitudinal
>>> from cleverly.longitudinal import LTMLE
>>> frame, _ = make_longitudinal(n=200, seed=0)
>>> result = LTMLE(
...     {"always": 1, "never": 0},
...     n_folds=1,
...     outcome_learner=LinearRegression(),
...     treatment_learner=LogisticRegression(max_iter=1000),
...     censoring_learner=LogisticRegression(max_iter=1000),
... ).fit(
...     frame,
...     outcome="Y",
...     treatment=["A1", "A2"],
...     baseline=["W1", "W2"],
...     time_varying=[[], ["L2"]],
...     censoring=["C1", "C2"],
... )
>>> rr = result.ratio("ey_regimen[always]", "ey_regimen[never]")
>>> rr.name, rr.scale
('rr_regimen[always vs never]', 'ratio')
LongitudinalResult.rmst(regimen: str, horizon: int, *, versus: str | None = None, name: str | None = None) → ParameterEstimate[source]#

The restricted mean survival time of a regimen up to a horizon.

With \(T\) the node of the first event and \(F(t)\) the reported risk,

\[\mathrm{RMST}(\tau) = E[\min(T, \tau)] = \tau - \sum_{t=1}^{\tau - 1} F(t),\]

with the curve \(-\sum_{t=1}^{\tau-1} IC_{F(t)}\). The unit is the node index. For nodes spaced \(\Delta\) apart, the RMST in calendar time is \(\Delta \times \mathrm{RMST}\). On a competing-risk fit, \(F\) is the sum of the cause-specific incidences. The estimate inherits the inference status of the risks it sums.

Parameters:
regimenstr

The regimen label.

horizonint

The restriction time \(\tau\), an integer from 2 to n_times + 1.

versusstr or None, default=None

A second regimen. The result is then the difference of the two RMSTs.

namestr or None, default=None

The name of the derived estimate. None gives rmst_regimen[a @ t=tau] or rmst_regimen[a vs b @ t=tau].

Returns:
ParameterEstimate

A "level" estimate, or a "difference" estimate with versus=.

Raises:
ValueError

When the fit reports no survival curve, when the horizon is outside the range, or when the fit omits a horizon below it.

Examples

>>> from sklearn.linear_model import LinearRegression, LogisticRegression
>>> from cleverly.datasets import make_longitudinal_survival
>>> from cleverly.longitudinal import LTMLE
>>> frame, _ = make_longitudinal_survival(n=300, seed=0)
>>> result = LTMLE(
...     {"always": 1, "never": 0},
...     n_folds=1,
...     outcome_learner=LinearRegression(),
...     treatment_learner=LogisticRegression(max_iter=1000),
...     censoring_learner=LogisticRegression(max_iter=1000),
... ).fit(
...     frame,
...     outcome=["Y1", "Y2"],
...     treatment=["A1", "A2"],
...     baseline=["W1", "W2"],
...     time_varying=[[], ["L2"]],
...     censoring=["C1", "C2"],
... )
>>> rmst = result.rmst("always", 3, versus="never")
>>> rmst.name, rmst.scale
('rmst_regimen[always vs never @ t=3]', 'difference')
LongitudinalResult.rmtl(regimen: str, horizon: int, cause: str | None = None, *, versus: str | None = None, name: str | None = None) → ParameterEstimate[source]#

The restricted mean time lost to one cause, up to a horizon.

With \(J\) the cause of the first event and \(F_j(t)\) its reported cumulative incidence,

\[\mathrm{RMTL}_j(\tau) = E[(\tau - \min(T, \tau)) 1\{J = j\}] = \sum_{t=1}^{\tau - 1} F_j(t),\]

with the curve \(\sum_{t=1}^{\tau-1} IC_{F_j(t)}\). On a one-event fit it is \(\tau - \mathrm{RMST}(\tau)\). The unit is the node index.

Parameters:
regimenstr

The regimen label.

horizonint

The restriction time \(\tau\), an integer from 2 to n_times + 1.

causestr or None, default=None

The cause. Required on a fit with two or more causes.

versusstr or None, default=None

A second regimen. The result is then the difference of the two RMTLs.

namestr or None, default=None

The name of the derived estimate. None gives rmtl_regimen[a, cause @ t=tau], or rmtl_regimen[a @ t=tau] on a one-event fit.

Returns:
ParameterEstimate

A "level" estimate, or a "difference" estimate with versus=.

Raises:
ValueError

When the fit reports no survival curve, when the horizon is outside the range, when the fit omits a horizon below it, or when the cause is missing or unknown.

Examples

>>> from sklearn.linear_model import LinearRegression, LogisticRegression
>>> from cleverly.datasets import make_longitudinal_survival
>>> from cleverly.longitudinal import LTMLE
>>> frame, _ = make_longitudinal_survival(n=300, seed=0)
>>> result = LTMLE(
...     {"always": 1, "never": 0},
...     n_folds=1,
...     outcome_learner=LinearRegression(),
...     treatment_learner=LogisticRegression(max_iter=1000),
...     censoring_learner=LogisticRegression(max_iter=1000),
... ).fit(
...     frame,
...     outcome=["Y1", "Y2"],
...     treatment=["A1", "A2"],
...     baseline=["W1", "W2"],
...     time_varying=[[], ["L2"]],
...     censoring=["C1", "C2"],
... )
>>> lost = result.rmtl("always", 3)
>>> rmst = result.rmst("always", 3)
>>> round(lost.psi + rmst.psi, 12)
3.0
LongitudinalResult.save(path: Any) → Any[source]#

Persist the complete fitted result to a trusted joblib artifact.

The artifact records cleverly.__version__. A load by a different version warns with VersionMismatchWarning and does not migrate the result.

Parameters:
pathpath-like

Destination file.

Returns:
Path

The destination path, as given.

LongitudinalResult.summary(*, protocol: Literal['full', 'fingerprint'] = 'full') → str[source]#

A printable report: the estimates, then the settings, then the leverage.

Parameters:
protocol{“full”, “fingerprint”}

"full" prints every field of the study protocol record. "fingerprint" prints only its schema and fingerprint, for a reader who has the record already.

Returns:
str

A printable report: the estimates, the settings, then the leverage.

LongitudinalResult.to_frame() → Any[source]#

One row per reported parameter, in the backend the data came from.

Built from to_dict(), so the columns are the ones a point-treatment fit reports under the same names. Two result objects in one library disagreeing on the name of every column is a worse cost than the one this saved.

Returns:
dataframe

One row per reported parameter, in the backend the data arrived in. A fit with a time grid adds a time column, the grid time of each parameter’s horizon.

LongitudinalResult.validate() → Any[source]#

Run the inexpensive default battery without refitting.

Returns:
ValidationReport

One item per validated check, read off stored artifacts.

Attributes#

LongitudinalResult.assessment_family: ClassVar[str] = 'longitudinal'#

Which family of assessment declarations applies to this result. See assessment_family; the method identity is fitted_method.

LongitudinalResult.bootstrap: BootstrapResult | None = None#

The full-refit bootstrap draws, None unless n_bootstrap > 0. A replayed fit never reruns the bootstrap.

LongitudinalResult.bootstrap_band: BootstrapBand | None = None#

The studentized bootstrap sup-t band over the estimates that supply inference, when n_bootstrap > 0 and simultaneous=True and two or more estimates supply it. Its support says whether a registered row lists the bootstrap_band kind.

LongitudinalResult.converged#

Whether every node’s targeting step reached its tolerance.

LongitudinalResult.diagnostics#

Unified support, nuisance, score, and refutation diagnostics.

LongitudinalResult.estimate#

The sole estimate, refusing ambiguity on a multi-parameter result.

LongitudinalResult.fitted_method: str = 'tmle'#
LongitudinalResult.fold_mechanisms: tuple[FoldMechanism, ...] = ()#

Each outer fold’s own mechanism, fitted on its training rows, on a cross-fitted SDR fit. Empty otherwise. A truncation replay reuses them.

LongitudinalResult.identified_effect: Any = None#

Causal-workflow metadata, present on every result created through CausalStudy.

LongitudinalResult.inference_status#

The inference status of the fit.

LTMLE.fit stamps one fit status on every estimate, and a parameter status (PARAMETER_STATUSES) on the parameters it applies to. This property is the fit status, through reported_status(), which leaves the parameter statuses out unless every estimate carries one. So it does not say whether one estimate supplies inference: read that estimate’s supplies_inference. "influence_curve" when the fit reports no estimate, because such a fit refuses nothing. A clustered fit with few clusters takes "few_cluster_plugin", as a point-treatment fit does.

LongitudinalResult.influence_curves#

Return influence curves by parameter alias.

LongitudinalResult.initial_hazards: InitialHazards | None = None#

The initial cause-specific hazards of a survival_model="hazard" fit, which the nuisance report and a truncation replay read. None on an iterated-mean fit.

LongitudinalResult.isotonic_moves: tuple[tuple[str, str | None, int, float, float], ...] = ()#

(regimen, cause, horizon, before, after) of every level the isotonic projection moved, empty when it moved none or isotonic=False.

LongitudinalResult.method: Any = None#
LongitudinalResult.msm: RegimenMSM | None = None#

The working model this fit projected onto, None if it declared none.

LongitudinalResult.msm_fits: tuple[MSMRegimenFit, ...] = ()#

One per cause, in the order the causes are reported.

LongitudinalResult.n#

Return the number of observations.

LongitudinalResult.parameter_index: dict[str, tuple[str, str | None, int]] | None = None#

name -> (regimen, cause, horizon) for every reported parameter, composed when the name was built. Empty on an end-of-study fit, which has neither index. None on a working-model fit, whose parameters are indexed by term.

LongitudinalResult.replayability#

Which assessment operations survive from the stored sequential artifacts.

LongitudinalResult.sensitivity#

Return the sensitivity-analysis facade.

LongitudinalResult.simulation: GFormulaReport | None = None#

On a ParametricGFormula fit, what the forward simulation drew: the draws, the models, the Monte Carlo share of each parameter and the fixed-dose model reliance. None on every other fit.

LongitudinalResult.simultaneous: SimultaneousBands | None = None#
LongitudinalResult.estimates: dict[str, ParameterEstimate]#
LongitudinalResult.fits: dict[str, RegimenFit]#
LongitudinalResult.data: LongitudinalData#
LongitudinalResult.config: LongitudinalConfig#
LongitudinalResult.scaler: OutcomeScaler#
LongitudinalResult.mechanism: Mechanism#
LongitudinalResult.folds: Folds#
LongitudinalResult.provenance: Provenance#
LongitudinalResult.parameter_keys: dict[str, Any]#
LongitudinalResult.assessment_cache: dict[str, Any]#

Assessment results keyed by operation and normalized arguments. Persistence writes this alongside the sequential artifacts it was computed from.

init=False for the reason cleverly.estimators.TMLEResult .assessment_cache gives: the key names the operation and its arguments and not the result, so a mapping handed to the constructor by dataclasses.replace would answer for a fit that never produced it.

LongitudinalResult.replay_recipe: _LongitudinalReplayRecipe#

Unfitted state for a complete bound-dependent recursion.