Causal-TS
Causal discovery for nonstationary time series.
Four discovery algorithms · GPU-accelerated CI tests, linear and nonlinear · Effect estimation.
Discovery Algorithms#
Constraint-based
Extends PC to time series with one or more C nonstationarity nodes. Three-phase: skeleton discovery → collider orientation → nonstationarity-based direction inference. CDNOTS+ replaces skeleton discovery with PCMCI+’s two-step approach for higher recall.
Autoregressive · Scalable
Causal Edge Discovery for Autoregressive processes with minimum-lag selection (dcor, Pearson). Two CI tests per candidate edge — O(d²) overall, supports single-target discovery.
Hybrid neural
Constraint-based skeleton + neural L0-gated refinement (Hard Concrete). Orientation from skeleton algorithm, edge existence from gate values.
Features#
From instant linear (ParCorrGPU) to distribution-free (DFCIT) and signature kernel (SigKCI) — unified interface on CUDA, MPS, or CPU.
Estimate causal effects, fit SCMs, run counterfactuals, and attribute anomalies to root causes — powered by DoWhy under the hood.
causal-ts discover, generate, evaluate, plot — full pipeline from the terminal. Network graphs and time-unrolled DAGs.
Pairwise-complete masking, VAR-EM imputation, and automatic discrete column detection with stratified testing.
Hands-on notebooks covering all algorithms, CI tests, effect estimation, and the full discovery-to-estimation pipeline.
Quick Example#
from causalts.synthetic_data.synthetic_datasets import load_dataset
from causalts.ci_tests import ParCorrGPU
from causalts import run_cdnots
from causalts.utils import evaluate_graph
from causalts.plotting import compare_graphs
# 1. Load a built-in dataset (ex2 = 6-Node Linear VAR)
data = load_dataset("ex2", seed=42, T=500)
df, ground_truth = data["df"], data["ground_truth"]
# 2. Run CDNOTS causal discovery
ci_test = ParCorrGPU(df.values, device="cpu")
res = run_cdnots(
df=df, indep_test=ci_test, num_lags=data["max_lag"],
include_C=True, alpha=0.05, stable=True,
)
# 3. Evaluate (exclude C dimension for shape match)
d = ground_truth.shape[0]
metrics = evaluate_graph(res.cg_tig[:d, :d, :], ground_truth)
print(f"F1={metrics['F1']:.3f}, SHD={metrics['SHD']}")
# 4. Visualize
res.plot()
compare_graphs(ground_truth, res.cg_tig[:d, :d, :],
var_names=list(df.columns))
Citation#
If you use Causal-TS in your research, please cite:
Fesanghary. “Causal-TS: A Python Library for Causal Discovery in High-Dimensional and Nonstationary Time Series.” arXiv:2607.24673, 2026.
Fesanghary. “CEDAR: Causal Edge Discovery for Autoregressive Processes.” arXiv:2607.20696, 2026.
Fesanghary, Havaldar. “GRACE: Gated Refinement for Accurate Causal Edge Discovery in High-Dimensional Time Series.” arXiv:2606.23880, 2026.
Sadeghi, Gopal, Fesanghary. “Causal Discovery from Nonstationary Time Series.” International Journal of Data Science and Analytics, 19, pp. 33–59, 2025. doi:10.1007/s41060-024-00679-7
Last updated: August 2026