Convergent Cross Mapping
Convergent Cross Mapping (CCM) tests whether variable X causally influences variable Y in a coupled dynamical system. It is based on the idea that if X drives Y, then the attractor reconstructed from Y will contain information about X.
How It Works
Section titled “How It Works”- Reconstruct the attractor from the effect variable Y
- Use nearest neighbors in this attractor to predict the cause variable X
- Repeat at increasing library sizes
- If prediction skill converges (improves with more data), X causes Y
Convergence is the key signature — it distinguishes true causation from mere correlation.
Using Convenience Wrappers
Section titled “Using Convenience Wrappers”The simplest way to run CCM:
import numpy as npfrom edmkit.ccm import with_simplex_projection
# X, Y: embedded time seriesn = len(X)lib_sizes = np.linspace(10, n, 20, dtype=int)
rho = with_simplex_projection( X, Y, lib_sizes=lib_sizes, library_pool=np.arange(n), prediction_pool=np.arange(n),)# rho[i] = mean correlation at lib_sizes[i]For S-Map-based CCM:
from edmkit.ccm import with_smap
rho = with_smap( X, Y, lib_sizes=lib_sizes, theta=3.0, library_pool=np.arange(n), prediction_pool=np.arange(n),)Custom Prediction Function
Section titled “Custom Prediction Function”Use the ccm function directly with any prediction function:
from edmkit.ccm import ccm
def my_predictor(X, Y, Q, *, mask=None): # Custom prediction logic ...
rho = ccm( X, Y, lib_sizes=lib_sizes, predict_func=my_predictor, library_pool=np.arange(n), prediction_pool=np.arange(n),)Bootstrap Analysis
Section titled “Bootstrap Analysis”Get per-sample correlation values for statistical testing:
from edmkit.ccm import bootstrap
samples = bootstrap( X, Y, lib_sizes=lib_sizes, predict_func=my_predictor, library_pool=np.arange(n), prediction_pool=np.arange(n), n_samples=100,)# samples shape: (100, len(lib_sizes))Reproducibility
Section titled “Reproducibility”Use make_sample_func for reproducible random sampling:
from edmkit.ccm import make_sample_func
rho = with_simplex_projection( X, Y, lib_sizes=lib_sizes, library_pool=np.arange(n), prediction_pool=np.arange(n), sample_func=make_sample_func(seed=42),)