Added
- LUCID (
causalts.confounders) — regime-adaptive deconfounding for causal discovery
under latent confounders.run_lucid(df, max_lag)diagnoses whether latent confounding
is sparse or pervasive from the residual spectrum (against a Marchenko–Pastur no-factor
null) and applies the matching correction, returning aLucidResult. Every
CausalResultnow also exposes.deconfound(),.tetrad_filter(), and.pds_filter()
so LUCID (or a fixed-strategy comparator) can be applied to a graph already discovered
with any algorithm, without re-running the skeleton search. See the new
Unobserved Confounders (LUCID) tutorial and the
causalts.confoundersAPI page. - DoWhy effects bridge.
validate_transition_graph()andhistory_sufficiency()
validate a lag-embedded graph (replacing the deprecatedfalsify_graph());
refute_effect()andsensitivity_analysis()stress-test an estimate;
build_identification_artifacts()/build_transition_artifacts()hand back a graph
and the frame it belongs with, for driving DoWhy directly. All are on the result
objects, andcausal-ts dowhy validate --testexposes the validators from the CLI. corrplot(..., diag="glyph")— renders the diagonal as an ordinary cell,
using the samemethodand colormap as the rest of the matrix. Intended for
directed matrices (a cause→effect adjacency or an edge-stability matrix),
where the diagonal is real data such as a self-loop rather than the trivial
1.0 of a correlation matrix. Significance markers and confidence-interval
overlays are still skipped on the diagonal.
Fixed
- Breaking.
estimate_effect()reported an unadjusted regression as an identified
causal effect — a lagged treatment had no parents, so no backdoor path was found. The
graph is now unrolled and the adjustment set verified against the fitted estimator.
ATEs change. - The GES, LGES and TGES baselines were substantially understated.
ges_discovery
read causal-learn's adjacency matrix with the endpoints transposed, and the vendored
GES search behindlges_discovery/tges_discoveryhad a broken CPDAG construction
that stopped LGES far short of convergence. Both are fixed and now apply temporal
background knowledge; F1 onbaseline_comparisonmoves from 0.125–0.522 to 0.636–0.949.
Any prior comparison against these baselines understates them. refute_effect()no longer reports an uncomputable refutation as a failure, and
refute_structure()returnsp_valueandadjusted_p_valueseparately. DoWhy's
renamed identification APIs are bound by capability, not version.causal-ts ci-test-info --test <name>now shows only the selected test's
summary instead of the full guide. Registered tests without a guide section
report a clear error; the default and--test alloutput are unchanged.- The CI test selection guide now covers all registered tests.
parcorr,
cmiknn,cmiknn-mixed-gpu,fisherz,chisqandgsquaredhad no entry,
soci-test-info --test <name>failed for them. Thecmiknn-gpuentry also
now notes that its permutation null stops early. priority=3andpriority=4(collider strength ordering) now raiseValueError
at the entry point, instead of failing with anAttributeErrorfrom inside
causal-learn after the skeleton search. They score each conflict over the full
powerset of the endpoints' neighbours — exponential in node degree — and were
never wired to a CI test. Usepriority=1(abstain) or2(keep first).detect_subsamplingraisesValueErroron a 1-D or single-variable input, instead of
failing inside NumPy withLinAlgError: 0-dimensional array given.- The generator in the Unobserved Confounders (LUCID) tutorial injected its true lag-1
edges after the recursion instead of inside it, so the simulated data did not match the
ground truth the notebook scored against. corrplotdropped the right and bottom edges of its grid border. All axes
spines are hidden, and the border was drawn withaxhline/axvlineat
exactly the axis limits, so half of each boundary line fell outside the clip
box. The border is now an unclipped rectangle and all four edges render.corrplot(..., colorbar=False)was ignored for the colour-only glyph methods
("color","shade"), which silently overrode an explicit argument and
forced callers to usecl_pos="n"instead.colorbar=Falsenow suppresses
the colorbar for every method.- Documentation: the "New in v0.26" banner linked to the example notebook with a
path relative to the site root, but the banner renders on every page — from
anything below the root (examples/,api/,getting_started/) it resolved to
a nonexistent nested path and 404'd. The link is now resolved per page.
Changed
-
run_cdnots_plusdefaults changed — this can change results for existing
callers that don't pin these parameters explicitly.run_cdnots_plusnow
follows PCMCI+'s conventions more closely: colliders that conflict during
orientation are abstained on rather than tie-broken (priority=1, was2),
MCI conditioning excludes only the exact tested lag rather than every lag of
a variable (legacy_mci_conds=False), the nonstationarity sink search stops
when candidates aren't clearly separated rather than always committing
(orient_margin=0.1, was unconditional), and the default significance level
isalpha=0.01(was0.05), matching PCMCI+ and empirically better for
CDNOTS+ (plainrun_cdnotsis unaffected and keepsalpha=0.05). In
aggregate these changes track PCMCI+ much more closely on stationary and
latently-confounded data while widening CDNOTS+'s advantage over plain
CDNOTS where nonstationarity is real. Pin the old values explicitly
(priority=2, legacy_mci_conds=True, orient_margin=0.0, alpha=0.05) to
reproduce prior behavior. -
causalts.ci_tests.SigKCIGPUno longer uses the optionalsigkernel
package: it crashed with a buffer dtype mismatch wheneversigkernelwas
installed, and measured slower than the existing pure-torch fallback at the
path lengths this test uses.SigKCIGPUnow always uses that fallback. -
The
guided_discoveryexample notebook is nowagentic_discovery("Agentic
Causal Discovery"), naming it after thecausal-ts-discoveryagent skill whose
workflow it walks through. The oldexamples/guided_discovery.htmlURL is gone;
the page is atexamples/agentic_discovery.html.