cleverly.sensitivity.positivity_report#

cleverly.sensitivity.positivity_report(result: TMLEResult) → PositivityReport[source]#

Compute overlap diagnostics for a fitted TMLE.

Two arms and more than two are reported by separate functions rather than one parameterised by arm count, because the questions differ. With two arms there is one propensity and overlap is symmetric: g near zero and g near one are the same problem seen from either arm, and the interesting split is treated versus control. With more there is no single margin and no mirror – each arm has its own denominator, which has to be reported and truncated in its own right. Collapsing the two into one function would mean picking definitions that read oddly in both.

A continuous treatment is refused rather than given a third branch. Every field of PositivityReport is per arm – quantiles of g(a | W), tail mass, effective sample size, weight share – and a dose has none, so the report would come back empty with a simplex_deviation of 1.0 computed from a zero-column mechanism: the largest value the field can take, reported as a finding. The question a shift fit actually has to answer is about the density ratio at the shifted dose, which check_policy_support() answers.

Parameters:
resultTMLEResult

A fitted result.

Returns:
PositivityReport

Overlap read off the stored nuisance fits, without refitting.

Raises:
CapabilityError

If the fit estimated no treatment mechanism. A missing-outcome NaturalCourseMean fit has no propensity for an arm-wise support report to read; inspect the missingness row of diagnostics.nuisance_models() instead.

DataError

If the treatment is continuous, which has no per-arm propensity either.