Phase Space Analysis

Epimodels provides tools for analyzing epidemic model dynamics using phase space reconstruction techniques from nonlinear time series analysis. These methods are useful for understanding the underlying attractor structure of disease dynamics, detecting chaos, and reconstructing system behavior from partial observations.

Reconstruction is based on Takens’ embedding theorem, which states that a scalar time series carries sufficient information to reconstruct the full phase space of a deterministic dynamical system.

Quick Start

from epimodels.continuous import SIR
from epimodels.tools.phase import find_optimal_embedding, phase_portrait

model = SIR()
model([1000, 1, 0], [0, 100], 1001, {'beta': 0.3, 'gamma': 0.1})

# Find optimal embedding parameters automatically
params = find_optimal_embedding(model.traces['I'])
print(f"Optimal tau={params['tau']}, dim={params['dim']}")

# Plot a phase portrait
phase_portrait(model.traces['S'], model.traces['I'])

Time Delay Embedding

TimeDelayEmbedding implements Takens’ embedding theorem for reconstructing the phase space from a scalar time series.

from epimodels.tools.phase import TimeDelayEmbedding
import numpy as np

t = np.linspace(0, 10, 1000)
data = np.sin(t) + 0.1 * np.random.randn(1000)

embedding = TimeDelayEmbedding(data, tau=10, dim=3)
embedded = embedding.embed()  # shape: (n_samples, 3)

Choosing optimal values for tau (time delay) and dim (embedding dimension) is critical for meaningful reconstruction. The module provides two automated methods.

Mutual Information

The mutual_information() method calculates average mutual information for different time delays. The first local minimum of the mutual information function is a good choice for the embedding delay tau.

embedding = TimeDelayEmbedding(data)
tau_opt, mi_values = embedding.mutual_information(tau_max=50)

# Visualize the results
embedding.plot_mutual_information(tau_max=50)

Cao’s Method

cao_embedding_dimension() estimates the minimum embedding dimension using the E1 statistic. When E1 saturates (stops increasing beyond a threshold), the corresponding dimension is sufficient.

embedding = TimeDelayEmbedding(data, tau=tau_opt)
dim_opt, e1_values = embedding.cao_embedding_dimension(dim_max=10)

# Visualize the results
embedding.plot_embedding_dimension(dim_max=10)

Automatic Parameter Selection

The convenience function find_optimal_embedding() combines both methods to find optimal tau and dim in one call:

from epimodels.tools.phase import find_optimal_embedding

params = find_optimal_embedding(data, tau_max=50, dim_max=10)
print(params['tau'])        # Optimal time delay
print(params['dim'])        # Optimal embedding dimension
print(params['mi_values'])  # Mutual information values
print(params['e1_values'])  # E1 statistic values

Phase Portraits

phase_portrait() creates a 2D phase portrait from two time series, typically from an epidemic model’s state variables. The trajectory can be colored by time to show temporal evolution.

from epimodels.tools.phase import phase_portrait
from epimodels.continuous import SIR

model = SIR()
model([1000, 1, 0], [0, 100], 1001, {'beta': 0.3, 'gamma': 0.1})

# S vs I phase portrait colored by time
phase_portrait(model.traces['S'], model.traces['I'])

# Custom styling
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
phase_portrait(
    model.traces['S'], model.traces['I'],
    ax=ax, color_by_time=False, color='darkblue', linewidth=1.5
)

API Reference