API Reference
Main Package
ts2net: Time Series to Networks
Clean API inspired by ts2vg, extended for multiple network methods.
- class ts2net.AppendResult(index, value, new_edges, n_nodes, n_edges)[source]
Bases:
objectResult of appending one point to an incremental HVG.
- Parameters:
index (int)
value (float)
new_edges (list[tuple])
n_nodes (int)
n_edges (int)
- index: int
- n_edges: int
- n_nodes: int
- new_edges: list[tuple]
- value: float
- class ts2net.BSTSSpec(level=True, trend=False, seasonal_periods=None, robust=False, standardize_residual=True)[source]
Bases:
objectSpecification for structural time series decomposition.
- Parameters:
level (bool, default True) – Include local level component
trend (bool, default False) – Include local linear trend
seasonal_periods (list of int, optional) – Seasonal periods (e.g., [24, 168] for hourly data with daily/weekly seasonality)
robust (bool, default False) – Use Student-t errors for heavy tails (slower, more robust)
standardize_residual (bool, default True) – Standardize residual before analysis (recommended)
- level: bool = True
- robust: bool = False
- seasonal_periods: List[int] | None = None
- standardize_residual: bool = True
- trend: bool = False
- class ts2net.CausalAnalysisResult(graph, edges, matrix, metrics, method, lag_by_pair=<factory>, alpha=0.05, adjusted=False, series_names=<factory>)[source]
Bases:
objectFull output of
run_causal_analysis().- Parameters:
graph (DiGraph)
edges (List[CausalEdgeResult])
matrix (NDArray[float64])
metrics (Dict[str, object])
method (str)
lag_by_pair (Dict[Tuple[int, int], int])
alpha (float)
adjusted (bool)
series_names (List[str])
- adjusted: bool = False
- alpha: float = 0.05
- edges: List[CausalEdgeResult]
- graph: DiGraph
- lag_by_pair: Dict[Tuple[int, int], int]
- matrix: NDArray[float64]
- method: str
- metrics: Dict[str, object]
- series_names: List[str]
- class ts2net.CausalWorkflowSpec(method='granger', max_lag=5, lag_search=True, te_lags=None, alpha=0.05, adjust_confounders=False, n_permutations=99, bootstrap_ci=False, n_bootstrap=100, bins=10, te_threshold=None, granger_method='linear', n_jobs=1, series_names=None)[source]
Bases:
objectConfiguration for
run_causal_analysis().- Parameters:
method (Literal['granger', 'transfer_entropy'])
max_lag (int)
lag_search (bool)
te_lags (List[int] | None)
alpha (float)
adjust_confounders (bool)
n_permutations (int)
bootstrap_ci (bool)
n_bootstrap (int)
bins (int)
te_threshold (float | None)
granger_method (Literal['linear', 'nonlinear'])
n_jobs (int)
series_names (List[str] | None)
- adjust_confounders: bool = False
- alpha: float = 0.05
- bins: int = 10
- bootstrap_ci: bool = False
- granger_method: Literal['linear', 'nonlinear'] = 'linear'
- lag_search: bool = True
- max_lag: int = 5
- method: Literal['granger', 'transfer_entropy'] = 'granger'
- n_bootstrap: int = 100
- n_jobs: int = 1
- n_permutations: int = 99
- series_names: List[str] | None = None
- te_lags: List[int] | None = None
- te_threshold: float | None = None
- class ts2net.DecisionPackage(title, graph_report=None, dynamic_report=None, causal_result=None, evidence=<factory>, confidence=<factory>, assumptions=<factory>, changes=<factory>, next_actions=<factory>)[source]
Bases:
objectEvidence bundle for decision support: graph + optional causal/dynamic context.
- Parameters:
title (str)
graph_report (GraphReport | None)
dynamic_report (DynamicChangeReport | None)
causal_result (CausalAnalysisResult | None)
evidence (list[str])
confidence (list[str])
assumptions (list[str])
changes (list[str])
next_actions (list[str])
- assumptions: list[str]
- causal_result: CausalAnalysisResult | None = None
- changes: list[str]
- confidence: list[str]
- dynamic_report: DynamicChangeReport | None = None
- evidence: list[str]
- graph_report: GraphReport | None = None
- next_actions: list[str]
- title: str
- class ts2net.DynamicAnalysisResult(sequence, regime, anomalies, transition_anomalies, persistence, churn, communities, roles, attribution=<factory>, method='hvg', window=50, step=1)[source]
Bases:
objectFull output of
run_dynamic_analysis().- Parameters:
sequence (RollingGraphSequence)
regime (dict[str, Any])
anomalies (NDArray[float64])
transition_anomalies (NDArray[float64])
persistence (dict[tuple[int, int], float])
churn (dict[str, NDArray[float64]])
communities (dict[str, Any])
roles (dict[int, list[str]])
attribution (dict[str, Any])
method (str)
window (int)
step (int)
- anomalies: NDArray[float64]
- anomalous_windows(threshold=2.0)[source]
Window indices with anomaly score above threshold.
- Parameters:
threshold (float)
- Return type:
NDArray[int64]
- attribution: dict[str, Any]
- churn: dict[str, NDArray[float64]]
- communities: dict[str, Any]
- method: str = 'hvg'
- persistence: dict[tuple[int, int], float]
- regime: dict[str, Any]
- roles: dict[int, list[str]]
- sequence: RollingGraphSequence
- step: int = 1
- transition_anomalies: NDArray[float64]
- window: int = 50
- class ts2net.DynamicChangeReport(result, title='Dynamic change report')[source]
Bases:
objectRegime breaks, edge persistence, and attribution from dynamic analysis.
- Parameters:
result (DynamicAnalysisResult)
title (str)
- result: DynamicAnalysisResult
- title: str = 'Dynamic change report'
- class ts2net.DynamicWorkflowSpec(method='hvg', window=50, step=1, output='stats', regime_metric='avg_degree', regime_method='zscore', regime_threshold=2.5, builder_kwargs=None, as_networkx=True)[source]
Bases:
objectConfiguration for
run_dynamic_analysis().- Parameters:
method (Literal['hvg', 'nvg', 'recurrence', 'transition'])
window (int)
step (int)
output (str)
regime_metric (str)
regime_method (Literal['zscore', 'cusum'])
regime_threshold (float)
builder_kwargs (dict[str, Any] | None)
as_networkx (bool)
- as_networkx: bool = True
- builder_kwargs: dict[str, Any] | None = None
- method: Literal['hvg', 'nvg', 'recurrence', 'transition'] = 'hvg'
- output: str = 'stats'
- regime_method: Literal['zscore', 'cusum'] = 'zscore'
- regime_metric: str = 'avg_degree'
- regime_threshold: float = 2.5
- step: int = 1
- window: int = 50
- class ts2net.EdgeExplanation(source, target, weight, method, parameters=<factory>, lag=None, p_value=None, significant=None, reason='')[source]
Bases:
objectWhy a directed or undirected edge exists.
- Parameters:
source (str | int)
target (str | int)
weight (float)
method (str)
parameters (dict[str, Any])
lag (int | None)
p_value (float | None)
significant (bool | None)
reason (str)
- lag: int | None = None
- method: str
- p_value: float | None = None
- parameters: dict[str, Any]
- reason: str = ''
- significant: bool | None = None
- source: str | int
- target: str | int
- weight: float
- class ts2net.FCIResult(pag, skeleton, separating_sets, variable_names, alpha, n_obs, method='fci', metadata=<factory>)[source]
Bases:
objectOutput of the FCI algorithm.
- Parameters:
pag (DiGraph)
skeleton (Graph)
separating_sets (Dict[Tuple[int, int], FrozenSet[int]])
variable_names (List[str])
alpha (float)
n_obs (int)
method (str)
metadata (Dict[str, object])
- alpha: float
- metadata: Dict[str, object]
- method: str = 'fci'
- n_obs: int
- pag: DiGraph
- separating_sets: Dict[Tuple[int, int], FrozenSet[int]]
- skeleton: Graph
- variable_names: List[str]
- class ts2net.Graph(edges, n_nodes, directed=False, weighted=False, _adjacency=None, _degrees=None, _in_degrees=None, _out_degrees=None)[source]
Bases:
objectLightweight graph representation.
Primary storage is edges + optional adjacency matrix. NetworkX conversion is lazy and optional.
- Parameters:
edges (List[Tuple])
n_nodes (int)
directed (bool)
weighted (bool)
_adjacency (Optional)
_degrees (NDArray | None)
_in_degrees (NDArray | None)
_out_degrees (NDArray | None)
- edges
Edge list (unweighted or weighted)
- Type:
list of (int, int) or (int, int, float)
- n_nodes
Number of nodes
- Type:
int
- directed
Whether graph is directed
- Type:
bool
- weighted
Whether edges have weights
- Type:
bool
Examples
>>> G = Graph(edges=[(0,1), (1,2)], n_nodes=3) >>> G.n_edges 2 >>> G.degree_sequence() array([1, 2, 1]) >>> nx_graph = G.as_networkx() # Optional conversion
- adjacency_matrix(format='sparse')[source]
Adjacency matrix (lazy, sparse by default).
- Parameters:
format (str, default "sparse") – Output format: “sparse” (CSR), “dense”, or “coo”
- Returns:
A – Adjacency matrix. Sparse by default to avoid memory blowup.
- Return type:
scipy.sparse.csr_matrix, scipy.sparse.coo_matrix, or array
- Raises:
ValueError – If format=”dense” and n_nodes > 50_000 (safety guardrail)
- as_networkx(force=False)[source]
Convert to NetworkX graph (optional dependency).
- Parameters:
force (bool, default False) – If False, refuse conversion for n > 200_000 nodes (safety guardrail)
- Returns:
G – NetworkX graph object
- Return type:
networkx.Graph or networkx.DiGraph
- Raises:
ImportError – If NetworkX is not installed
ValueError – If n_nodes > 200_000 and force=False
- degree_sequence()[source]
Degree sequence (cached).
For undirected graphs returns total degree; for directed graphs returns out-degree (for backward compatibility).
- Returns:
degrees
- Return type:
NDArray[int64] of shape (n_nodes,)
- directed: bool = False
- edges: List[Tuple]
- edges_coo()[source]
Return edges in COO format (coordinate arrays).
- Returns:
src (array (n_edges,)) – Source node indices
dst (array (n_edges,)) – Destination node indices
weight (array (n_edges,) or None) – Edge weights (if weighted), None otherwise
- Return type:
Tuple[NDArray, NDArray, NDArray | None]
- in_degree_sequence()[source]
In-degree sequence for directed graphs (cached).
- Returns:
in_degrees
- Return type:
NDArray[int64] of shape (n_nodes,)
- property n_edges: int
Number of edges
- n_nodes: int
- network_metrics(include=None, sample_size=None, **kwargs)[source]
Compute advanced network metrics (clustering, path lengths, modularity).
- Parameters:
include (list, optional) – Metrics to include: [“clustering”, “path_lengths”, “modularity”] If None, includes all metrics
sample_size (int, optional) – For large graphs, sample nodes/pairs for expensive computations
**kwargs – Additional arguments passed to metric functions
- Returns:
Dictionary with network metrics
- Return type:
dict
Examples
>>> from ts2net import HVG >>> import numpy as np >>> x = np.random.randn(100) >>> hvg = HVG() >>> hvg.build(x) >>> metrics = hvg._graph.network_metrics() >>> print(f"Clustering: {metrics['avg_clustering']:.3f}") >>> print(f"Avg path length: {metrics['avg_path_length']:.3f}") >>> print(f"Modularity: {metrics['modularity']:.3f}")
- out_degree_sequence()[source]
Out-degree sequence for directed graphs (cached).
- Returns:
out_degrees
- Return type:
NDArray[int64] of shape (n_nodes,)
- summary(include_triangles=False)[source]
Graph summary statistics (computed from edges/degrees, no dense matrix).
- Parameters:
include_triangles (bool, default False) – If True, compute triangle count (requires edge list, slower)
- Returns:
stats – Dictionary with n_nodes, n_edges, avg_degree, std_degree, density, and optionally triangles. For directed graphs, includes in/out degree statistics and irreversibility_score.
- Return type:
dict
- weighted: bool = False
- class ts2net.GraphReport(title, provenance, topology, top_hubs, edge_explanations=<factory>, node_summaries=<factory>, instability_notes=<factory>)[source]
Bases:
objectHuman-readable summary of graph topology and key actors.
- Parameters:
title (str)
provenance (Provenance)
topology (dict[str, Any])
top_hubs (list[tuple[str | int, int]])
edge_explanations (list[EdgeExplanation])
node_summaries (list[NodeRoleSummary])
instability_notes (list[str])
- edge_explanations: list[EdgeExplanation]
- instability_notes: list[str]
- node_summaries: list[NodeRoleSummary]
- provenance: Provenance
- title: str
- top_hubs: list[tuple[str | int, int]]
- topology: dict[str, Any]
- class ts2net.HVG(weighted=False, limit=None, only_degrees=False, output='edges', directed=False, weight_mode=None)[source]
Bases:
SklearnBuildMixinHorizontal Visibility Graph (HVG).
Two nodes i < j are connected if every intermediate value is strictly below the lower of the two endpoints:
x[k] < min(x[i], x[j]) for all i < k < j
Complexity: O(n) time and space (monotone stack algorithm).
Key invariants (random i.i.d. series): - Mean degree → 4 as n → ∞ (Luque et al. 2009) - Degree distribution follows P(k) ~ (1/3)(2/3)^(k-2) for k ≥ 2
- Parameters:
weighted (bool) – Edge weights = abs(y_i - y_j)
limit (int, optional) – Maximum temporal distance between connected nodes.
Nonemeans unconstrained (default). Useful for very long series where distant connections are not meaningful.output ({"edges", "degrees", "stats"}, default "edges") –
"edges"stores the full edge list;"degrees"stores only the degree sequence (fast, low memory);"stats"stores only summary statistics (lowest memory).directed (bool, default False) – Produce a directed graph with edges pointing forward in time (i → j for i < j). Enables irreversibility analysis.
only_degrees (bool)
weight_mode (str | None)
References
Luque, B., Lacasa, L., Ballesteros, F., & Luque, J. (2009). Horizontal visibility graphs: Exact results for random time series. Physical Review E, 80(4), 046103. https://doi.org/10.1103/PhysRevE.80.046103
Examples
>>> import numpy as np >>> from ts2net import HVG >>> x = np.random.randn(1000) >>> hvg = HVG().build(x) # build() returns self for chaining >>> print(hvg.n_nodes, hvg.n_edges) >>> degrees = hvg.degree_sequence >>> A = hvg.adjacency_matrix() # sparse CSR by default >>> G_nx = hvg.as_networkx() # Optional
- adjacency_matrix(format='sparse')[source]
Adjacency matrix.
- Parameters:
format ({"sparse", "coo", "dense"}, default "sparse") –
"sparse"returns a SciPy CSR matrix."coo"returns a SciPy COO matrix."dense"returns a NumPy array; refused for n > 50 000 nodes (would require ≥ 20 GB RAM).- Returns:
A – Symmetric adjacency matrix of shape (n_nodes, n_nodes).
- Return type:
csr_matrix | coo_matrix | ndarray
- as_networkx(force=False)[source]
Convert to a NetworkX graph.
- Parameters:
force (bool, default False) – If False, raises for n > 200 000 nodes to prevent accidental allocation of very large objects.
- Returns:
G
- Return type:
nx.Graph or nx.DiGraph
- build(x)[source]
Build HVG from time series.
Equivalent to
fit(x); returnsselffor method chaining.- Parameters:
x (array-like of shape (n,)) – Input time series.
- Returns:
self
- Return type:
- degree_sequence()[source]
Node degree sequence.
- Returns:
d – Out-degree for directed graphs; total degree for undirected.
- Return type:
NDArray[int64] of shape (n_nodes,)
- property edges
Edge list (None if output=’degrees’ or ‘stats’)
- edges_coo()[source]
Edge list in COO (coordinate) format.
- Returns:
rows (NDArray[int64] — source node indices)
cols (NDArray[int64] — target node indices)
weights (NDArray[float64] or None — edge weights (None if unweighted))
- Return type:
Tuple[NDArray[int64], NDArray[int64], NDArray[float64] | None]
- fit(x)
Store and validate input; does not build until transform().
- Parameters:
x (NDArray[float64])
- Return type:
SklearnBuildMixin
- fit_transform(x)
Fit and transform in one step.
- Parameters:
x (NDArray[float64])
- Return type:
Graph
- property n_edges
Number of edges
- property n_nodes
Number of nodes
- network_metrics(include=None, sample_size=None, **kwargs)[source]
Compute advanced network metrics (clustering, path lengths, modularity).
- Parameters:
include (list, optional) – Metrics to include: [“clustering”, “path_lengths”, “modularity”] If None, includes all metrics
sample_size (int, optional) – For large graphs, sample nodes/pairs for expensive computations
**kwargs – Additional arguments passed to metric functions (e.g., method, weight, resolution, seed)
- Returns:
Dictionary with network metrics: - Clustering: avg_clustering, transitivity - Path lengths: avg_path_length, diameter, radius - Modularity: modularity, n_communities
- Return type:
dict
Examples
>>> from ts2net import HVG >>> import numpy as np >>> x = np.random.randn(100) >>> hvg = HVG() >>> hvg.build(x) >>> metrics = hvg.network_metrics() >>> print(f"Clustering: {metrics['avg_clustering']:.3f}") >>> print(f"Avg path length: {metrics['avg_path_length']:.3f}") >>> print(f"Modularity: {metrics['modularity']:.3f}")
- stats(include_triangles=False)[source]
Summary statistics (memory efficient, no dense matrix)
- Parameters:
include_triangles (bool)
- Return type:
dict
- test_significance(metric='density', method='shuffle', n_surrogates=200, alpha=0.05, rng=None, **kwargs)[source]
Test significance of a network metric against null distribution.
- Parameters:
metric (str, default "density") – Metric to test. Options: “density”, “deg_mean”, “deg_std”, “avg_clustering”, “assortativity”, or any key from stats()
method (str, default "shuffle") – Surrogate generation method: “shuffle”, “phase”, “circular”, “iaaft”, “block_bootstrap”
n_surrogates (int, default 200) – Number of surrogate series to generate
alpha (float, default 0.05) – Significance level (two-tailed)
rng (np.random.Generator, optional) – Random number generator
**kwargs – Additional arguments for surrogate generation (e.g., block_size for block_bootstrap)
- Returns:
result – Significance test result
- Return type:
NetworkSignificanceResult
Examples
>>> from ts2net import HVG >>> import numpy as np >>> x = np.random.randn(100) >>> hvg = HVG() >>> hvg.build(x) >>> result = hvg.test_significance(metric="density", method="phase", n_surrogates=100) >>> print(result)
- transform()
Build the network from data stored by fit().
- Return type:
Graph
- class ts2net.IncrementalHVG(weighted=False, limit=None, directed=False, _values=<factory>, _edges=<factory>)[source]
Bases:
objectIncrementally extend an HVG as new observations arrive.
Appending a point at the end only creates edges involving the new index; existing edges among earlier nodes are unchanged.
- Parameters:
weighted (bool, default False) – Weight edges by absolute value difference.
limit (int, optional) – Maximum temporal distance between connected nodes.
directed (bool, default False) – If True, edges point forward in time (i -> j, i < j).
_values (list[float])
_edges (list[tuple])
- append(value)[source]
Append one observation and add any new visibility edges.
- Returns:
New node index, edges born on this step, and totals.
- Return type:
- Parameters:
value (float)
- directed: bool = False
- classmethod from_series(x, **kwargs)[source]
Build incrementally from an existing series (equivalent to batch).
- Parameters:
x (NDArray[float64])
- Return type:
- limit: int | None = None
- property n_edges: int
- property n_nodes: int
- property values: NDArray[float64]
- weighted: bool = False
- class ts2net.MultiplexGraph(layers=<factory>, n_nodes=0)[source]
Bases:
objectContainer for named graph layers.
- layersdict[str, nx.Graph]
Named edge layers.
- n_nodesint
Number of nodes (must be consistent across layers).
- Parameters:
layers (dict[str, Graph])
n_nodes (int)
- add_layer(name, G)[source]
Add or replace a layer, aligning node sets across layers.
- Parameters:
name (str)
G (Graph)
- Return type:
None
- aggregate_adjacency(strategy='union', weights=None)[source]
Merge layer adjacencies into a single matrix.
uniontakes max weight per edge;intersectionrequires all layers;sumadds weighted adjacencies.- Parameters:
strategy (Literal['union', 'intersection', 'sum'])
weights (dict[str, float] | None)
- Return type:
ndarray
- edges_in_layers(u, v)[source]
Return layer names where edge (u, v) exists.
- Parameters:
u (int)
v (int)
- Return type:
set[str]
- layers: dict[str, Graph]
- n_nodes: int = 0
- class ts2net.MultiscaleGraphs(method='hvg', scales=None, coarse_method='mean', output='stats', **method_kwargs)[source]
Bases:
objectMultiscale graph analysis for time series.
Analyzes time series at multiple temporal scales by coarse-graining and computing graph features at each scale. Creates a scale signature (feature vector across scales) useful for detection stability.
Examples
>>> x = np.random.randn(1000) >>> ms = MultiscaleGraphs(method='hvg', scales=[1, 2, 4, 8]) >>> ms.fit(x) >>> signature = ms.scale_signature() >>> # signature is a dict with features at each scale >>> print(signature['avg_degree']) # Array of avg_degree at each scale
- Parameters:
method (str)
scales (Optional[List[int]])
coarse_method (str)
output (str)
- fit(x)[source]
Fit the multiscale analyzer to a time series.
- Parameters:
x (array (n_points,)) – Input time series
- Returns:
self – Returns self for method chaining
- Return type:
- fit_transform(x, features=None)[source]
Fit and return scale signature in one step.
- Parameters:
x (array (n_points,)) – Input time series
features (list of str, optional) – Features to include in signature
- Returns:
Scale signature dictionary
- Return type:
dict[str, array]
- scale_signature(features=None)[source]
Get scale signature (feature values across scales).
- Parameters:
features (list of str, optional) – List of feature names to include. If None, uses common features: [‘n_nodes’, ‘n_edges’, ‘avg_degree’, ‘std_degree’, ‘density’]
- Returns:
Dictionary mapping feature names to arrays of length n_scales. Each array contains the feature value at each scale.
- Return type:
dict[str, array]
Examples
>>> ms = MultiscaleGraphs(method='hvg', scales=[1, 2, 4]) >>> ms.fit(x) >>> signature = ms.scale_signature() >>> print(signature['avg_degree']) # [deg_scale1, deg_scale2, deg_scale4]
- class ts2net.NVG(weighted=False, limit=None, only_degrees=False, output='edges', max_edges=None, max_edges_per_node=None, max_memory_mb=None, weight_mode=None)[source]
Bases:
SklearnBuildMixinNatural Visibility Graph (NVG).
Two nodes i < j are connected if the straight line between (i, x[i]) and (j, x[j]) lies strictly above all intermediate data points:
x[k] < x[i] + (x[j] - x[i]) * (k - i) / (j - i) for all i < k < j
NVG is a superset of HVG: every HVG edge is also an NVG edge.
Complexity: O(n log n) average (sweep-line algorithm).
- Parameters:
weighted (bool or str, default False) – See HVG for weight mode options.
limit (int, optional) – Horizon limit — maximum temporal distance between connected nodes. Recommended for series > 10 000 points (2 000–5 000 suggested).
output ({"edges", "degrees", "stats"}, default "edges") – Controls what is stored after build().
only_degrees (bool)
max_edges (int | None)
max_edges_per_node (int | None)
max_memory_mb (float | None)
weight_mode (str | None)
References
Lacasa, L., Luque, B., Ballesteros, F., Luque, J., & Nuño, J. C. (2008). From time series to complex networks: The visibility graph. PNAS, 105(13), 4972–4975. https://doi.org/10.1073/pnas.0709247105
Examples
>>> import numpy as np >>> from ts2net import NVG >>> x = np.random.randn(500) >>> nvg = NVG(limit=500).build(x) >>> print(nvg.n_nodes, nvg.n_edges)
- adjacency_matrix(format='sparse')[source]
Adjacency matrix.
- Parameters:
format ({"sparse", "coo", "dense"}, default "sparse") –
"sparse"returns a SciPy CSR matrix."coo"returns a SciPy COO matrix."dense"returns a NumPy array; refused for n > 50 000 nodes (would require ≥ 20 GB RAM).- Returns:
A – Symmetric adjacency matrix of shape (n_nodes, n_nodes).
- Return type:
csr_matrix | coo_matrix | ndarray
- as_networkx(force=False)[source]
Convert to a NetworkX graph.
- Parameters:
force (bool, default False) – If False, raises for n > 200 000 nodes to prevent accidental allocation of very large objects.
- Returns:
G
- Return type:
nx.Graph or nx.DiGraph
- build(x)[source]
Build NVG from time series.
Equivalent to
fit(x); returnsselffor method chaining.- Parameters:
x (array-like of shape (n,)) – Input time series.
- Returns:
self
- Return type:
- property edges
- edges_coo()[source]
Edge list in COO (coordinate) format.
- Returns:
rows (NDArray[int64] — source node indices)
cols (NDArray[int64] — target node indices)
weights (NDArray[float64] or None — edge weights (None if unweighted))
- Return type:
Tuple[NDArray[int64], NDArray[int64], NDArray[float64] | None]
- fit(x)
Store and validate input; does not build until transform().
- Parameters:
x (NDArray[float64])
- Return type:
SklearnBuildMixin
- fit_transform(x)
Fit and transform in one step.
- Parameters:
x (NDArray[float64])
- Return type:
Graph
- property n_edges: int
Number of edges.
- property n_nodes: int
Number of nodes (equals length of input series).
- network_metrics(include=None, sample_size=None, **kwargs)[source]
Compute advanced network metrics (clustering, path lengths, modularity).
- Parameters:
include (list, optional) – Metrics to include: [“clustering”, “path_lengths”, “modularity”] If None, includes all metrics
sample_size (int, optional) – For large graphs, sample nodes/pairs for expensive computations
**kwargs – Additional arguments passed to metric functions (e.g., method, weight, resolution, seed)
- Returns:
Dictionary with network metrics: - Clustering: avg_clustering, transitivity - Path lengths: avg_path_length, diameter, radius - Modularity: modularity, n_communities
- Return type:
dict
Examples
>>> from ts2net import HVG >>> import numpy as np >>> x = np.random.randn(100) >>> hvg = HVG() >>> hvg.build(x) >>> metrics = hvg.network_metrics() >>> print(f"Clustering: {metrics['avg_clustering']:.3f}") >>> print(f"Avg path length: {metrics['avg_path_length']:.3f}") >>> print(f"Modularity: {metrics['modularity']:.3f}")
- stats(include_triangles=False)[source]
Summary statistics (no dense matrix required).
- Parameters:
include_triangles (bool)
- Return type:
dict
- test_significance(metric='density', method='shuffle', n_surrogates=200, alpha=0.05, rng=None, **kwargs)[source]
Test significance of a network metric against null distribution.
- Parameters:
metric (str, default "density") – Metric to test. Options: “density”, “deg_mean”, “deg_std”, “avg_clustering”, “assortativity”, or any key from stats()
method (str, default "shuffle") – Surrogate generation method: “shuffle”, “phase”, “circular”, “iaaft”, “block_bootstrap”
n_surrogates (int, default 200) – Number of surrogate series to generate
alpha (float, default 0.05) – Significance level (two-tailed)
rng (np.random.Generator, optional) – Random number generator
**kwargs – Additional arguments for surrogate generation (e.g., block_size for block_bootstrap)
- Returns:
result – Significance test result
- Return type:
NetworkSignificanceResult
Examples
>>> from ts2net import NVG >>> import numpy as np >>> x = np.random.randn(100) >>> nvg = NVG() >>> nvg.build(x) >>> result = nvg.test_significance(metric="density", method="phase", n_surrogates=100) >>> print(result)
- transform()
Build the network from data stored by fit().
- Return type:
Graph
- class ts2net.NetworkBuilder(*args, **kwargs)[source]
Bases:
ProtocolProtocol implemented by all network graph builders.
- property n_edges: int
- property n_nodes: int
- class ts2net.NetworkFeatureExtractor(method='hvg', output='stats', features=None, prefix=None, **builder_kwargs)[source]
Bases:
BaseEstimator,TransformerMixinExtract network summary features from time series for sklearn pipelines.
Each input row is treated as one univariate time series. The transformer builds a network with the chosen method and returns summary statistics as a numeric feature vector.
- Parameters:
method ({"hvg", "nvg", "recurrence", "transition"}, default "hvg") – Network construction method.
output ({"stats", "degrees"}, default "stats") – Builder output mode.
"stats"is memory-efficient and recommended for panel data.features (list of str, optional) – Subset of summary statistics to return. Defaults to all available stats.
prefix (str, optional) – Prefix for feature names (e.g.
"hvg_").**builder_kwargs – Additional keyword arguments passed to the network builder (e.g.
limit=2000for NVG,rule="knn", k=5for recurrence).
Examples
>>> import numpy as np >>> from sklearn.pipeline import Pipeline >>> from sklearn.preprocessing import StandardScaler >>> from sklearn.linear_model import LogisticRegression >>> from ts2net.sklearn import NetworkFeatureExtractor >>> X = np.random.randn(40, 200) >>> y = np.array([0] * 20 + [1] * 20) >>> pipe = Pipeline([ ... ("net", NetworkFeatureExtractor(method="hvg")), ... ("scale", StandardScaler()), ... ("clf", LogisticRegression(max_iter=500)), ... ]) >>> pipe.fit(X, y).score(X, y)
- fit(X, y=None)[source]
Learn feature names from a representative sample.
- Parameters:
X (NDArray[float64])
y (NDArray[Any] | None)
- Return type:
- fit_transform(X, y=None, **fit_params)
Fit to data, then transform it.
Fits transformer to X and y with optional parameters fit_params and returns a transformed version of X.
- Parameters:
X (array-like of shape (n_samples, n_features)) – Input samples.
y (array-like of shape (n_samples,) or (n_samples, n_outputs), default=None) – Target values (None for unsupervised transformations).
**fit_params (dict) – Additional fit parameters. Pass only if the estimator accepts additional params in its fit method.
- Returns:
X_new – Transformed array.
- Return type:
ndarray array of shape (n_samples, n_features_new)
- get_feature_names_out(input_features=None)[source]
Return output feature names for sklearn >= 1.0.
- Parameters:
input_features (Sequence[str] | None)
- Return type:
ndarray
- get_metadata_routing()
Get metadata routing of this object.
Please check User Guide on how the routing mechanism works.
- Returns:
routing – A
MetadataRequestencapsulating routing information.- Return type:
MetadataRequest
- get_params(deep=True)
Get parameters for this estimator.
- Parameters:
deep (bool, default=True) – If True, will return the parameters for this estimator and contained subobjects that are estimators.
- Returns:
params – Parameter names mapped to their values.
- Return type:
dict
- set_output(*, transform=None)
Set output container.
Refer to the user guide for more details and sphx_glr_auto_examples_miscellaneous_plot_set_output.py for an example on how to use the API.
- Parameters:
transform ({"default", "pandas", "polars"}, default=None) –
Configure output of transform and fit_transform.
”default”: Default output format of a transformer
”pandas”: DataFrame output
”polars”: Polars output
None: Transform configuration is unchanged
Added in version 1.4: “polars” option was added.
- Returns:
self – Estimator instance.
- Return type:
estimator instance
- set_params(**params)
Set the parameters of this estimator.
The method works on simple estimators as well as on nested objects (such as
Pipeline). The latter have parameters of the form<component>__<parameter>so that it’s possible to update each component of a nested object.- Parameters:
**params (dict) – Estimator parameters.
- Returns:
self – Estimator instance.
- Return type:
estimator instance
- class ts2net.NetworkFeatureSelector(k=10, score_func='mutual_info', feature_names=None)[source]
Bases:
BaseEstimator,TransformerMixinSelect top-k network features using univariate scoring.
Intended for use after
NetworkFeatureExtractororRollingNetworkFeatureExtractorin a sklearn pipeline.- Parameters:
k (int, default 10) – Number of features to retain.
score_func ({"f_classif", "mutual_info"}, default "mutual_info") – Univariate scoring function.
feature_names (list of str, optional) – Names of input features (for
get_feature_names_out).
Examples
>>> import numpy as np >>> from sklearn.pipeline import Pipeline >>> from ts2net.sklearn import NetworkFeatureExtractor, NetworkFeatureSelector >>> X = np.random.randn(40, 100) >>> y = np.array([0] * 20 + [1] * 20) >>> ext = NetworkFeatureExtractor(method="hvg") >>> Xf = ext.fit_transform(X) >>> names = list(ext.get_feature_names_out()) >>> sel = NetworkFeatureSelector(k=3, feature_names=names) >>> sel.fit(Xf, y).transform(Xf).shape[1] == 3 True
- fit_transform(X, y=None, **fit_params)
Fit to data, then transform it.
Fits transformer to X and y with optional parameters fit_params and returns a transformed version of X.
- Parameters:
X (array-like of shape (n_samples, n_features)) – Input samples.
y (array-like of shape (n_samples,) or (n_samples, n_outputs), default=None) – Target values (None for unsupervised transformations).
**fit_params (dict) – Additional fit parameters. Pass only if the estimator accepts additional params in its fit method.
- Returns:
X_new – Transformed array.
- Return type:
ndarray array of shape (n_samples, n_features_new)
- get_feature_names_out(input_features=None)[source]
- Parameters:
input_features (Sequence[str] | None)
- Return type:
ndarray
- get_metadata_routing()
Get metadata routing of this object.
Please check User Guide on how the routing mechanism works.
- Returns:
routing – A
MetadataRequestencapsulating routing information.- Return type:
MetadataRequest
- get_params(deep=True)
Get parameters for this estimator.
- Parameters:
deep (bool, default=True) – If True, will return the parameters for this estimator and contained subobjects that are estimators.
- Returns:
params – Parameter names mapped to their values.
- Return type:
dict
- set_output(*, transform=None)
Set output container.
Refer to the user guide for more details and sphx_glr_auto_examples_miscellaneous_plot_set_output.py for an example on how to use the API.
- Parameters:
transform ({"default", "pandas", "polars"}, default=None) –
Configure output of transform and fit_transform.
”default”: Default output format of a transformer
”pandas”: DataFrame output
”polars”: Polars output
None: Transform configuration is unchanged
Added in version 1.4: “polars” option was added.
- Returns:
self – Estimator instance.
- Return type:
estimator instance
- set_params(**params)
Set the parameters of this estimator.
The method works on simple estimators as well as on nested objects (such as
Pipeline). The latter have parameters of the form<component>__<parameter>so that it’s possible to update each component of a nested object.- Parameters:
**params (dict) – Estimator parameters.
- Returns:
self – Estimator instance.
- Return type:
estimator instance
- class ts2net.NodeRoleSummary(node, role, degree, betweenness=None, anomaly=False, notes='')[source]
Bases:
objectRole and centrality context for one node.
- Parameters:
node (str | int)
role (str)
degree (int)
betweenness (float | None)
anomaly (bool)
notes (str)
- anomaly: bool = False
- betweenness: float | None = None
- degree: int
- node: str | int
- notes: str = ''
- role: str
- exception ts2net.NotBuiltError[source]
Bases:
Ts2NetError,ValueErrorRaised when a network builder method is called before build()/fit().
- add_note()
Exception.add_note(note) – add a note to the exception
- args
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- class ts2net.PCResult(cpdag, skeleton, separating_sets, variable_names, alpha, n_obs, method='pc', metadata=<factory>)[source]
Bases:
objectOutput of the PC algorithm.
- Parameters:
cpdag (DiGraph)
skeleton (Graph)
separating_sets (Dict[Tuple[int, int], FrozenSet[int]])
variable_names (List[str])
alpha (float)
n_obs (int)
method (str)
metadata (Dict[str, object])
- alpha: float
- cpdag: DiGraph
- metadata: Dict[str, object]
- method: str = 'pc'
- n_obs: int
- separating_sets: Dict[Tuple[int, int], FrozenSet[int]]
- skeleton: Graph
- variable_names: List[str]
- class ts2net.PerformanceContract(method, time_complexity, memory_complexity, recommended_output, notes='')[source]
Bases:
objectExpected time and memory scaling for a builder.
- Parameters:
method (str)
time_complexity (str)
memory_complexity (str)
recommended_output (str)
notes (str)
- memory_complexity: str
- method: str
- notes: str = ''
- recommended_output: str
- time_complexity: str
- class ts2net.PipelineConfig(dataset, graphs, output, sampling=<factory>, windows=<factory>, bsts=<factory>, logging=<factory>)[source]
Bases:
objectComplete pipeline configuration.
- Parameters:
dataset (DatasetConfig)
graphs (GraphsConfig)
output (OutputConfig)
sampling (SamplingConfig)
windows (WindowsConfig)
bsts (BSTSConfig)
logging (LoggingConfig)
- bsts: BSTSConfig
- dataset: DatasetConfig
- classmethod from_dict(data)[source]
Create PipelineConfig from dictionary (e.g., from YAML).
- Parameters:
data (Dict[str, Any])
- Return type:
- classmethod from_yaml(yaml_path)[source]
Load configuration from YAML file.
- Parameters:
yaml_path (str | Path)
- Return type:
- graphs: GraphsConfig
- logging: LoggingConfig
- output: OutputConfig
- sampling: SamplingConfig
- windows: WindowsConfig
- class ts2net.Provenance(method, parameters=<factory>, window=None, n_series=None, n_points=None)[source]
Bases:
objectHow a graph or analysis was produced.
- Parameters:
method (str)
parameters (dict[str, Any])
window (tuple[int, int] | None)
n_series (int | None)
n_points (int | None)
- method: str
- n_points: int | None = None
- n_series: int | None = None
- parameters: dict[str, Any]
- window: tuple[int, int] | None = None
- class ts2net.RecurrenceNetwork(m=None, tau=1, rule='knn', k=5, epsilon=0.1, metric='euclidean', only_degrees=False, output='edges')[source]
Bases:
SklearnBuildMixinRecurrence Network.
A recurrence network is derived from a recurrence plot. After delay-embedding the series into an m-dimensional phase space, two states i, j are connected if their distance falls below a threshold (
rule="epsilon") or if one is among the other’s k nearest neighbours (rule="knn").- Parameters:
m (int, optional) – Embedding dimension.
Nonemeans no embedding (1-D, i.e., the raw series is used as the phase-space trajectory).tau (int, default 1) – Time delay for Takens embedding.
rule ({"knn", "epsilon"}, default "knn") –
"knn"connects each point to its k nearest neighbours."epsilon"connects all pairs closer than epsilon.k (int, default 5) – Number of nearest neighbours (
rule="knn"only).epsilon (float, default 0.1) – Recurrence threshold (
rule="epsilon"only).metric (str, default "euclidean") – Distance metric for phase-space proximity.
output ({"edges", "degrees", "stats"}, default "edges") – Controls what is stored after build().
only_degrees (bool)
References
Marwan, N., Donges, J. F., Zou, Y., Donner, R. V., & Kurths, J. (2009). Complex network approach for recurrence analysis of time series. Physics Letters A, 373(46), 4246–4254. https://doi.org/10.1016/j.physleta.2009.09.042
Examples
>>> import numpy as np >>> from ts2net import RecurrenceNetwork >>> x = np.sin(np.linspace(0, 8*np.pi, 300)) + 0.1*np.random.randn(300) >>> rn = RecurrenceNetwork(rule="epsilon", epsilon=0.3).build(x) >>> print(rn.n_nodes, rn.n_edges)
- adjacency_matrix(format='sparse')[source]
Adjacency matrix.
- Parameters:
format ({"sparse", "coo", "dense"}, default "sparse") –
"sparse"returns a SciPy CSR matrix."coo"returns a SciPy COO matrix."dense"returns a NumPy array; refused for n > 50 000 nodes (would require ≥ 20 GB RAM).- Returns:
A – Symmetric adjacency matrix of shape (n_nodes, n_nodes).
- Return type:
csr_matrix | coo_matrix | ndarray
- as_networkx(force=False)[source]
Convert to a NetworkX graph.
- Parameters:
force (bool, default False) – If False, raises for n > 200 000 nodes to prevent accidental allocation of very large objects.
- Returns:
G
- Return type:
nx.Graph or nx.DiGraph
- build(x)[source]
Build recurrence network from time series.
- Parameters:
x (array-like of shape (n,)) – Input time series.
- Returns:
self
- Return type:
- property edges
- edges_coo()[source]
Edge list in COO (coordinate) format.
- Returns:
rows (NDArray[int64] — source node indices)
cols (NDArray[int64] — target node indices)
weights (NDArray[float64] or None — edge weights (None if unweighted))
- Return type:
Tuple[NDArray[int64], NDArray[int64], NDArray[float64] | None]
- fit(x)
Store and validate input; does not build until transform().
- Parameters:
x (NDArray[float64])
- Return type:
SklearnBuildMixin
- fit_transform(x)
Fit and transform in one step.
- Parameters:
x (NDArray[float64])
- Return type:
Graph
- property n_edges: int
Number of edges.
- property n_nodes: int
Number of nodes (equals length of input series).
- stats(include_triangles=False)[source]
Summary statistics (no dense matrix required).
- Parameters:
include_triangles (bool)
- Return type:
dict
- transform()
Build the network from data stored by fit().
- Return type:
Graph
- class ts2net.RollingGraphSequence(method='hvg', window=50, step=1, output='stats', builder_kwargs=<factory>, graphs_nx=<factory>, stats=<factory>, window_starts=<factory>)[source]
Bases:
objectGraph sequence built from sliding windows over one time series.
- methodstr
Builder:
hvg,nvg,recurrence,transition.- window, stepint
Sliding window width and step.
- outputstr
Builder output mode (
stats,degrees,edges).
- builder_kwargs
Extra arguments for the network builder.
- Parameters:
method (Literal['hvg', 'nvg', 'recurrence', 'transition'])
window (int)
step (int)
output (str)
builder_kwargs (dict[str, Any])
graphs_nx (list[Graph])
stats (list[dict[str, Any]])
window_starts (NDArray[int64])
- builder_kwargs: dict[str, Any]
- classmethod from_series(x, window, step=1, method='hvg', output='stats', as_networkx=True, **builder_kwargs)[source]
Build a rolling graph sequence from a univariate series.
- Parameters:
x (NDArray[float64])
window (int)
step (int)
method (Literal['hvg', 'nvg', 'recurrence', 'transition'])
output (str)
as_networkx (bool)
- Return type:
- graphs_nx: list[Graph]
- method: Literal['hvg', 'nvg', 'recurrence', 'transition'] = 'hvg'
- output: str = 'stats'
- persistence()[source]
Edge persistence across all windows.
- Return type:
dict[tuple[int, int], float]
- stat_series(key)[source]
Extract one summary statistic across windows.
- Parameters:
key (str)
- Return type:
NDArray[float64]
- stats: list[dict[str, Any]]
- step: int = 1
- window: int = 50
- window_starts: NDArray[int64]
- class ts2net.RollingNetworkFeatureExtractor(method='hvg', window=64, step=32, aggregates=('mean', 'std'), features=None, prefix=None, **builder_kwargs)[source]
Bases:
BaseEstimator,TransformerMixinExtract network features from rolling windows, aggregated per series.
Each input row is one time series. Windows are built along the series, graph statistics are computed per window, then aggregated (mean, std, etc.) into a fixed-length feature vector suitable for sklearn.
- Parameters:
method (str, default "hvg") – Network method:
hvg,nvg,recurrence,transition.window (int, default 64) – Window width in time points.
step (int, default 32) – Step between consecutive windows.
aggregates (list of str, default ("mean", "std")) – Aggregations applied to each window-level statistic.
features (list of str, optional) – Window stats to include (default: core graph stats).
prefix (str, optional) – Feature name prefix.
**builder_kwargs – Extra arguments for the network builder.
Examples
>>> import numpy as np >>> from ts2net.sklearn import RollingNetworkFeatureExtractor >>> X = np.random.randn(20, 300) >>> ext = RollingNetworkFeatureExtractor(window=50, step=25) >>> ext.fit(X).transform(X).shape[0] == 20 True
- fit_transform(X, y=None, **fit_params)
Fit to data, then transform it.
Fits transformer to X and y with optional parameters fit_params and returns a transformed version of X.
- Parameters:
X (array-like of shape (n_samples, n_features)) – Input samples.
y (array-like of shape (n_samples,) or (n_samples, n_outputs), default=None) – Target values (None for unsupervised transformations).
**fit_params (dict) – Additional fit parameters. Pass only if the estimator accepts additional params in its fit method.
- Returns:
X_new – Transformed array.
- Return type:
ndarray array of shape (n_samples, n_features_new)
- get_feature_names_out(input_features=None)[source]
- Parameters:
input_features (Sequence[str] | None)
- Return type:
ndarray
- get_metadata_routing()
Get metadata routing of this object.
Please check User Guide on how the routing mechanism works.
- Returns:
routing – A
MetadataRequestencapsulating routing information.- Return type:
MetadataRequest
- get_params(deep=True)
Get parameters for this estimator.
- Parameters:
deep (bool, default=True) – If True, will return the parameters for this estimator and contained subobjects that are estimators.
- Returns:
params – Parameter names mapped to their values.
- Return type:
dict
- set_output(*, transform=None)
Set output container.
Refer to the user guide for more details and sphx_glr_auto_examples_miscellaneous_plot_set_output.py for an example on how to use the API.
- Parameters:
transform ({"default", "pandas", "polars"}, default=None) –
Configure output of transform and fit_transform.
”default”: Default output format of a transformer
”pandas”: DataFrame output
”polars”: Polars output
None: Transform configuration is unchanged
Added in version 1.4: “polars” option was added.
- Returns:
self – Estimator instance.
- Return type:
estimator instance
- set_params(**params)
Set the parameters of this estimator.
The method works on simple estimators as well as on nested objects (such as
Pipeline). The latter have parameters of the form<component>__<parameter>so that it’s possible to update each component of a nested object.- Parameters:
**params (dict) – Estimator parameters.
- Returns:
self – Estimator instance.
- Return type:
estimator instance
- class ts2net.SINDyResult(model, coefficients, feature_names, state_names, t=None, spec=<factory>, backend_used='pysindy')[source]
Bases:
objectOutcome of
fit_sindy().- Parameters:
model (Any)
coefficients (NDArray[float64])
feature_names (list[str])
state_names (list[str])
t (NDArray[float64] | float | list[NDArray[float64]] | None)
spec (SINDySpec)
backend_used (str)
- backend_used: str = 'pysindy'
- coefficients: NDArray[float64]
- feature_names: list[str]
- model: Any
- simulate(x0, t)[source]
Integrate the discovered model from
x0overt.- Parameters:
x0 (NDArray[float64])
t (NDArray[float64])
- Return type:
NDArray[float64]
- state_names: list[str]
- t: NDArray[float64] | float | list[NDArray[float64]] | None = None
- class ts2net.SINDySpec(polynomial_degree=3, threshold=0.1, alpha=0.05, differentiation_order=2, optimizer='stlsq', backend='auto')[source]
Bases:
objectConfiguration for a SINDy fit.
Defaults follow PySINDy tutorial 1: finite-difference derivatives, polynomial library, and sequentially-thresholded least squares (STLSQ).
- Parameters:
polynomial_degree (int)
threshold (float)
alpha (float)
differentiation_order (int)
optimizer (str)
backend (Literal['auto', 'rust', 'pysindy'])
- alpha: float = 0.05
- backend: Literal['auto', 'rust', 'pysindy'] = 'auto'
- differentiation_order: int = 2
- optimizer: str = 'stlsq'
- polynomial_degree: int = 3
- threshold: float = 0.1
- class ts2net.TransitionNetwork(symbolizer='ordinal', order=3, delay=1, tie_rule='stable', bins=5, normalize=True, sparse=False, only_degrees=False, output='edges')[source]
Bases:
SklearnBuildMixinTransition Network (Ordinal Partition Network).
The time series is symbolised — each subsequence of length
order+1is mapped to its rank-order pattern (an ordinal pattern). A directed graph is then built where nodes are distinct patterns and a weighted edge (i → j) records how often pattern i is immediately followed by pattern j.The resulting graph captures the Markov-like transition dynamics of the series and is sensitive to nonlinear structure invisible to linear methods.
- Parameters:
symbolizer ({"ordinal", "equal_width", "equal_freq", "kmeans"}) – How to discretise the series into symbolic states.
"ordinal"(default) uses rank-order patterns — invariant to monotone transformations and well-studied analytically.order (int, default 3) – Pattern length =
order + 1.order=3gives 3! = 6 possible patterns. Larger values capture longer-range dependencies at the cost of sparsity (and needing longer series).delay (int, default 1) – Sampling delay for pattern extraction.
output ({"edges", "degrees", "stats"}, default "edges") – Controls what is stored after build().
tie_rule (str)
bins (int)
normalize (bool)
sparse (bool)
only_degrees (bool)
References
Small, M. (2013). Complex networks from time series: Capturing nonlinear dynamics. Chaos, 23(3), 033127. https://doi.org/10.1063/1.4818261
Examples
>>> import numpy as np >>> from ts2net import TransitionNetwork >>> x = np.random.randn(500) >>> tn = TransitionNetwork(order=3).build(x) >>> print(tn.n_nodes, tn.n_edges) # nodes = distinct patterns, directed
- adjacency_matrix(format='sparse')[source]
Adjacency matrix.
- Parameters:
format ({"sparse", "coo", "dense"}, default "sparse") –
"sparse"returns a SciPy CSR matrix."coo"returns a SciPy COO matrix."dense"returns a NumPy array; refused for n > 50 000 nodes (would require ≥ 20 GB RAM).- Returns:
A – Symmetric adjacency matrix of shape (n_nodes, n_nodes).
- Return type:
csr_matrix | coo_matrix | ndarray
- as_networkx(force=False)[source]
Convert to a NetworkX graph.
- Parameters:
force (bool, default False) – If False, raises for n > 200 000 nodes to prevent accidental allocation of very large objects.
- Returns:
G
- Return type:
nx.Graph or nx.DiGraph
- build(x)[source]
Build transition network from time series.
- Parameters:
x (array-like of shape (n,)) – Input time series.
- Returns:
self
- Return type:
- property edges
- edges_coo()[source]
Edge list in COO (coordinate) format.
- Returns:
rows (NDArray[int64] — source node indices)
cols (NDArray[int64] — target node indices)
weights (NDArray[float64] or None — edge weights (None if unweighted))
- Return type:
Tuple[NDArray[int64], NDArray[int64], NDArray[float64] | None]
- fit(x)
Store and validate input; does not build until transform().
- Parameters:
x (NDArray[float64])
- Return type:
SklearnBuildMixin
- fit_transform(x)
Fit and transform in one step.
- Parameters:
x (NDArray[float64])
- Return type:
Graph
- property n_edges: int
Number of edges.
- property n_nodes: int
Number of nodes (equals length of input series).
- stats(include_triangles=False)[source]
Summary statistics (no dense matrix required).
- Parameters:
include_triangles (bool)
- Return type:
dict
- transform()
Build the network from data stored by fit().
- Return type:
Graph
- exception ts2net.Ts2NetError[source]
Bases:
ExceptionBase exception for ts2net errors.
- add_note()
Exception.add_note(note) – add a note to the exception
- args
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception ts2net.ValidationError[source]
Bases:
Ts2NetError,ValueErrorRaised when input data or parameters fail validation.
- add_note()
Exception.add_note(note) – add a note to the exception
- args
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- class ts2net.VisibilityAsymmetryResult(irreversibility_score, temporal_asymmetry_index, forward_backward_ratio, graph, in_degrees, out_degrees, node_asymmetry, stats, method='dhvg', metadata=<factory>)[source]
Bases:
objectDirected visibility graph asymmetry metrics.
- Parameters:
irreversibility_score (float)
temporal_asymmetry_index (float)
forward_backward_ratio (float)
graph (DiGraph)
in_degrees (NDArray[float64])
out_degrees (NDArray[float64])
node_asymmetry (NDArray[float64])
stats (Dict[str, float])
method (str)
metadata (Dict[str, object])
- forward_backward_ratio: float
- graph: DiGraph
- in_degrees: NDArray[float64]
- irreversibility_score: float
- metadata: Dict[str, object]
- method: str = 'dhvg'
- node_asymmetry: NDArray[float64]
- out_degrees: NDArray[float64]
- stats: Dict[str, float]
- temporal_asymmetry_index: float
- ts2net.adaptive_recurrence_network(x, target_density=0.05, m=None, tau=1, metric='euclidean', output='edges')[source]
Recurrence network with epsilon chosen for a target edge density.
- Parameters:
x (array (n,)) – Input series.
target_density (float, default 0.05) – Desired edge density (fraction of possible pairs).
m (int) – Embedding dimension and delay (
m=Noneuses raw series).tau (int) – Embedding dimension and delay (
m=Noneuses raw series).metric (str) – Distance metric for recurrence.
output (str)
- Returns:
builder (RecurrenceNetwork) – Fitted builder.
epsilon (float) – Selected threshold.
- Return type:
tuple[RecurrenceNetwork, float]
- ts2net.approximate_knn_network(D, k=5, weighted=True, directed=False)[source]
Build a k-NN graph from a precomputed distance matrix.
Uses scikit-learn
NearestNeighborswithmetric='precomputed'. For very large panels in raw feature space, prefernet_knn_approx(X, metric='euclidean')(pynndescent).- Parameters:
D (array (n, n)) – Pairwise distance matrix.
k (int, default 5) – Neighbors per node.
weighted (bool, default True) – Store distances as edge weights.
directed (bool, default False) – If True, return a directed graph.
- Returns:
G (networkx.Graph or DiGraph)
A (adjacency matrix)
- Return type:
tuple[Graph, NDArray[float64]]
- ts2net.approximate_knn_panel(X, k=5, metric='euclidean', weighted=True, directed=False, n_neighbors=None)[source]
Approximate k-NN on a feature panel using pynndescent (fast at large n).
Requires
pip install ts2net[approx].- Parameters:
X (NDArray[float64])
k (int)
metric (str)
weighted (bool)
directed (bool)
n_neighbors (int | None)
- Return type:
tuple[Graph, NDArray[float64]]
- ts2net.build_decision_package(x=None, *, G=None, method='hvg', parameters=None, window=50, step=1, causal=None, dynamic=None, multivariate=None, title=None)[source]
Assemble evidence, confidence, assumptions, changes, and next actions.
Provide
Gdirectly, orx(univariate) to run dynamic analysis, ormultivariatewithcausalfor multivariate causal packages.- Parameters:
x (NDArray[float64] | None)
G (Graph | DiGraph | None)
method (str)
parameters (dict[str, Any] | None)
window (int)
step (int)
causal (CausalAnalysisResult | None)
dynamic (DynamicAnalysisResult | None)
multivariate (NDArray[float64] | None)
title (str | None)
- Return type:
- ts2net.build_dynamic_change_report(result, *, title=None)[source]
Wrap
DynamicAnalysisResultas a change report.- Parameters:
result (DynamicAnalysisResult)
title (str | None)
- Return type:
- ts2net.build_graph_from_config(series, graph_type, config, include_triangles=False)[source]
Build a graph from configuration and return statistics.
- Parameters:
series (array) – Input time series
graph_type (str) – Graph type: ‘hvg’, ‘nvg’, ‘recurrence’, or ‘transition’
config (GraphConfig) – Configuration object for the graph type
include_triangles (bool) – Whether to include triangle counting in stats (computationally expensive)
- Returns:
Graph statistics dictionary
- Return type:
dict
- ts2net.build_graph_report(G, *, method, parameters=None, title=None, n_points=None, max_edges=10)[source]
Summarise topology, hubs, roles, and sample edge explanations.
- Parameters:
G (networkx.Graph or DiGraph) – Built graph (optionally with edge attrs: weight, lag, p_value).
method (str) – Builder or workflow name (e.g.
"hvg","granger").parameters (dict, optional) – Builder parameters for provenance.
title (str, optional) – Report heading.
n_points (int, optional) – Original series length.
max_edges (int, default 10) – Number of strongest edges to explain.
- Return type:
- ts2net.build_network(x, method, **kwargs)[source]
Build network from time series (factory pattern).
- Parameters:
x (array) – Time series
method (str) – ‘hvg’, ‘nvg’, ‘recurrence’, ‘transition’
**kwargs – Method-specific parameters
- Returns:
graph – Built network with .edges, .degree_sequence(), etc.
- Return type:
Graph-like object
Examples
>>> x = np.random.randn(1000) >>> hvg = build_network(x, 'hvg') >>> rn = build_network(x, 'recurrence', m=3, rule='knn', k=5)
- ts2net.build_windows(x, window, step=1, method='hvg', output='stats', aggregate=None, n_jobs=1, executor=None, streaming=False, **method_kwargs)[source]
Build graph statistics per window (memory efficient for large series).
- Parameters:
x (array (n_points,)) – Input time series
window (int) – Window width (number of time points per window)
step (int, default 1) – Step size between consecutive windows
method (str, default "hvg") – Network method: ‘hvg’, ‘nvg’, ‘recurrence’, ‘transition’
output (str, default "stats") – Output mode: ‘stats’ (recommended), ‘degrees’, or ‘edges’
aggregate (str, optional) – Aggregation function for stats: ‘mean’, ‘std’, ‘min’, ‘max’
n_jobs (int, default 1) – Parallel workers for independent windows. Use -1 for all CPUs.
executor (str, optional) – Distributed backend
daskorrayfor embarrassingly parallel windows.streaming (bool, default False) – If True, avoid materializing the full
(n_windows, window)matrix.**method_kwargs – Additional parameters for the network builder
- Returns:
Per-window stats arrays, or a single array when
aggregateis set.- Return type:
dict[str, np.ndarray] or np.ndarray
- ts2net.build_windows_streaming(x, window, step=1, method='hvg', output='stats', aggregate=None, **method_kwargs)[source]
Stream graph statistics per window (constant memory in window count).
Unlike
ts2net.api_windows.build_windows(), this does not allocate an(n_windows, window)matrix.- Yields:
window_index (int)
start_index (int)
stats (dict or float) – Per-window stats, or a single aggregated value if
aggregateis set.
- Parameters:
x (NDArray[float64])
window (int)
step (int)
method (str)
output (str)
aggregate (str | None)
- Return type:
Iterator[tuple[int, int, dict[str, float] | float]]
- ts2net.causal_network_metrics(G, weight='weight')[source]
Summarize a directed causal network.
- Parameters:
G (networkx.DiGraph) – Directed causal network.
weight (str, default "weight") – Edge attribute for strength-based metrics.
- Returns:
Global metrics (density, avg_in_strength, avg_out_strength, avg_path_length on the largest weakly connected component) and per-node
directionalityindices.- Return type:
dict
- ts2net.causal_strength(G, source, target, weight='weight')[source]
Path-based causal strength from
sourcetotarget.Uses the maximum-weight directed path (log-sum of edge weights when weights are probabilities or TE values). Returns 0 when no path exists.
- Parameters:
G (networkx.DiGraph) – Directed causal network.
source (int) – Node indices.
target (int) – Node indices.
weight (str, default "weight") – Edge attribute used as path weight.
- Returns:
Maximum path strength (product of edge weights along best path).
- Return type:
float
- ts2net.coarse_grain(x, scale, method='mean')[source]
Coarse-grain a time series by aggregating points at a given scale.
- Parameters:
x (array (n_points,)) – Input time series
scale (int) – Coarse-graining scale (number of points to aggregate)
method (str, default "mean") – Aggregation method: “mean”, “median”, “max”, “min”, “std”
- Returns:
Coarse-grained time series
- Return type:
array (n_points // scale,)
Examples
>>> x = np.arange(12.0) >>> coarse_grain(x, scale=3, method="mean") array([1., 4., 7., 10.])
- ts2net.community_labels(G)[source]
Assign community ids using connected components (fallback for sparse graphs).
For denser graphs with networkx >= 2.8, uses greedy modularity communities when available.
- Parameters:
G (Graph)
- Return type:
dict[int, int]
- ts2net.compare_feature_sets(X, y, feature_sets, estimator=None, cv=5, scoring='accuracy')[source]
Cross-validate classifiers on multiple feature representations.
- Parameters:
X (array (n_series, n_timesteps)) – Raw time series (unused if all sets are precomputed).
y (array (n_series,)) – Class labels.
feature_sets (dict) – Mapping name → feature matrix
(n_series, n_features).estimator (sklearn estimator, optional) – Classifier (default: scaled logistic regression).
cv (int, default 5) – Cross-validation folds.
scoring (str, default "accuracy") – sklearn scoring metric.
- Returns:
Per feature set:
mean_score,std_score,n_features.- Return type:
dict
Examples
>>> import numpy as np >>> from ts2net.sklearn import NetworkFeatureExtractor, compare_feature_sets >>> from ts2net.sklearn.benchmarks import statistical_baseline_features >>> rng = np.random.default_rng(0) >>> X = rng.standard_normal((40, 120)) >>> y = np.array([0] * 20 + [1] * 20) >>> net = NetworkFeatureExtractor(method="hvg").fit_transform(X) >>> base, _ = statistical_baseline_features(X) >>> results = compare_feature_sets( ... X, y, {"network": net, "statistical": base} ... ) >>> "network" in results True
- ts2net.conditional_transfer_entropy(x, y, z, lag=1, bins=10)[source]
Compute conditional transfer entropy from X to Y given Z.
Conditional transfer entropy accounts for confounding variables Z, measuring the direct causal influence from X to Y.
CTE(X→Y|Z) = H(Y_t | Y_{t-1}, Z_{t-1}) - H(Y_t | Y_{t-1}, X_{t-1}, Z_{t-1})
- Parameters:
x (array (n,)) – Source time series
y (array (n,)) – Target time series
z (array (n,)) – Conditioning time series (confounding variable)
lag (int, default 1) – Time lag for past values
bins (int, default 10) – Number of bins for discretization
- Returns:
cte – Conditional transfer entropy from X to Y given Z (non-negative, bits)
- Return type:
float
Examples
>>> import numpy as np >>> x = np.random.randn(1000) >>> z = np.random.randn(1000) >>> y = 0.5 * x[:-1] + 0.3 * z[:-1] + 0.1 * np.random.randn(999) >>> y = np.concatenate([[0], y]) >>> cte = conditional_transfer_entropy(x, y, z, lag=1) >>> print(f"Conditional transfer entropy X→Y|Z: {cte:.4f} bits")
- ts2net.correlation_matrix(X, method='pearson')[source]
Pairwise correlation matrix for a panel of time series.
- ts2net.correlation_network(X, method='pearson', rule='knn', k=5, threshold=0.5, epsilon=0.3, weighted=True)[source]
Build a network from pairwise correlations.
- Parameters:
X (array (n_series, n_points)) – Panel of time series (nodes = series).
method (str) – Correlation measure.
rule ({"knn", "epsilon", "threshold", "complete"}) – How to sparsify the network.
k (int) – Neighbors for k-NN rule.
threshold (float) – Minimum |correlation| to keep an edge (
rule="threshold").epsilon (float) – Maximum correlation distance for epsilon-NN.
weighted (bool) – Store |correlation| as edge weight.
- Returns:
G (networkx.Graph)
C (correlation matrix)
D (distance matrix (1 - |C|))
- Return type:
tuple[Graph, NDArray[float64], NDArray[float64]]
- ts2net.create_graph_builder(graph_type, config, n_points=None)[source]
Create a graph builder from configuration using dispatch pattern.
- Parameters:
graph_type (str) – Graph type: ‘hvg’, ‘nvg’, ‘recurrence’, or ‘transition’
config (GraphConfig) – Configuration object for the graph type
n_points (int, optional) – Number of points in series (used for safety checks)
- Returns:
Configured graph builder instance
- Return type:
GraphBuilder
- Raises:
ValueError – If graph_type is unknown or configuration is invalid
- ts2net.cross_recurrence_network(x, y, epsilon=None, target_density=0.05)[source]
Cross-recurrence network between two time series.
Node
iconnects to nodejwhen|x[i]-y[j]| < epsilon(bivariate recurrence in index-aligned embedding).- Parameters:
x (array (n,)) – Aligned time series.
y (array (n,)) – Aligned time series.
epsilon (float, optional) – Threshold; if None, chosen from
target_density.target_density (float) – Used when
epsilonis None.
- Returns:
G (networkx.Graph)
R (array (n, n) bool cross-recurrence matrix)
- Return type:
tuple[Graph, NDArray[bool]]
- ts2net.decompose(series, spec)[source]
Decompose time series into structural components using state space model.
Uses statsmodels state space models for fast MLE estimation.
- Parameters:
series (array) – Input time series
spec (BSTSSpec) – Decomposition specification
- Returns:
Components, residual, and variance estimates
- Return type:
DecompositionResult
- Raises:
ImportError – If statsmodels is not installed
ValueError – If series is too short or constant
- ts2net.detect_regime_changes(values, method='zscore', threshold=2.5, min_segment=3)[source]
Detect regime changes in a sequence of graph metrics.
- Parameters:
values (array (n_windows,)) – Metric sampled at each graph window (e.g. average degree).
method ({"zscore", "cusum"}, default "zscore") –
zscoreflags large jumps in first differences.cusumuses a cumulative-sum deviation test.threshold (float, default 2.5) – Detection threshold (z-score or normalized CUSUM scale).
min_segment (int, default 3) – Minimum windows between consecutive breaks.
- Returns:
break_indices,scores,segments(start indices per regime).- Return type:
dict
- ts2net.directed_visibility_analysis(x, weighted=False, limit=None, compare_reversed=True)[source]
Analyze temporal asymmetry via a directed horizontal visibility graph.
Directed HVG edges point forward in time (i → j for i < j), enabling irreversibility and time-arrow statistics useful for fault detection and causal asymmetry screening.
- Parameters:
x (array (n,)) – Input time series.
weighted (bool, default False) – Use absolute-difference edge weights.
limit (int, optional) – Maximum temporal distance between connected nodes.
compare_reversed (bool, default True) – When True, compute temporal asymmetry vs the time-reversed series.
- Returns:
Irreversibility score, asymmetry index, graph, and degree sequences.
- Return type:
Examples
>>> import numpy as np >>> x = np.linspace(0, 1, 200) >>> result = directed_visibility_analysis(x) >>> result.irreversibility_score >= 0 True
References
Lacasa et al. (2008). From time series to complex networks: The visibility graph. PNAS, 105(13), 4972–4975.
- ts2net.directionality_index(G, node=None, weight='weight')[source]
Net causal directionality for one or all nodes.
DI(v) = (out_strength - in_strength) / (out_strength + in_strength)
Values near +1 indicate net causal emitter; near -1 net receiver.
- Parameters:
G (networkx.DiGraph) – Directed causal network.
node (int, optional) – Node index. If None, returns dict for all nodes.
weight (str, default "weight") – Edge attribute for strength.
- Returns:
Directionality index in [-1, 1].
- Return type:
float or dict[int, float]
- ts2net.edge_birth_death(G_prev, G_next, undirected=True)[source]
Compare consecutive graphs and identify edge births and deaths.
- Returns:
Keys:
born,died,persisted,n_births,n_deaths.- Return type:
dict
- Parameters:
G_prev (Graph)
G_next (Graph)
undirected (bool)
- ts2net.edge_persistence(graphs, undirected=True)[source]
Fraction of windows each edge appears in.
- Returns:
Edge -> persistence score in [0, 1].
- Return type:
dict
- Parameters:
graphs (list[Graph])
undirected (bool)
- ts2net.edge_transition_anomalies(births, deaths, jaccard=None)[source]
Anomaly scores for graph transitions (length
n_windows - 1).Combines z-scored edge births, deaths, and optional Jaccard drop.
- Parameters:
births (NDArray[float64])
deaths (NDArray[float64])
jaccard (NDArray[float64] | None)
- Return type:
NDArray[float64]
- ts2net.edges_to_csr(edges, n_nodes, directed=False, weighted=False, dtype=<class 'numpy.float64'>)[source]
Build a CSR matrix directly from an edge list.
Avoids constructing a dense adjacency for large sparse graphs.
- Parameters:
edges (list[tuple])
n_nodes (int)
directed (bool)
weighted (bool)
dtype (type)
- Return type:
csr_matrix
- ts2net.entropy_max_symbolize(x, n_bins=8)[source]
Equal-frequency (entropy-maximizing) symbolization.
Assigns symbols so each bin has approximately equal count.
- Parameters:
x (NDArray[float64])
n_bins (int)
- Return type:
NDArray[int32]
- ts2net.estimate_window_job_memory_mb(window, method='hvg')[source]
Rough per-window memory estimate in megabytes.
Uses performance contracts as guidance for logging and capacity planning.
- Parameters:
window (int)
method (str)
- Return type:
float
- ts2net.event_sequence_network(x, *, method='peaks', thresh=None, min_separation=1, edge_rule='window', max_interval=10)[source]
Build a network whose nodes are detected events.
- Parameters:
x (array (n,)) – Input time series.
method (str) – Event detection:
thresholdorpeaks(seeevents_from_ts).thresh (float, optional) – Detection threshold.
min_separation (int) – Minimum samples between events.
edge_rule ({"consecutive", "window"}) –
consecutivelinks adjacent events;windowlinks all pairs withinmax_interval.max_interval (int) – Maximum time gap for
edge_rule="window".
- Returns:
G (networkx.Graph) – Nodes are event indices with
timeattribute.events (array) – Event time indices.
- Return type:
tuple[Graph, NDArray[int64]]
- ts2net.event_sync_network(X, *, method='peaks', thresh=None, min_separation=1, adaptive=True, rule='knn', k=3, threshold=0.3)[source]
Multivariate event synchronization network.
Nodes represent time series; edge weight is event synchronization
qfrom
tssim_event_sync. Distance =1 - q.- Xarray (n_series, n_points)
Panel of series.
- method, thresh, min_separation
Event detection parameters per series.
- adaptivebool
Adaptive sync window in
tssim_event_sync.- rule{“knn”, “threshold”, “complete”}
Network sparsification.
- k, threshold
Sparsification parameters.
G : networkx.Graph sync_matrix : array (n_series, n_series) synchronization strengths event_sets : list of event index arrays per series
- Parameters:
X (NDArray[float64])
method (str)
thresh (float | None)
min_separation (int)
adaptive (bool)
rule (str)
k (int)
threshold (float)
- Return type:
tuple[Graph, NDArray[float64], list[NDArray[int64]]]
- ts2net.explain_edge_from_graph(G, u, v, method, parameters=None)[source]
Build an explanation from edge attributes on
G.- Parameters:
G (Graph)
u (Any)
v (Any)
method (str)
parameters (dict[str, Any] | None)
- Return type:
- ts2net.explain_edges_from_causal(result)[source]
Convert causal workflow edges to
EdgeExplanationrows.- Parameters:
result (CausalAnalysisResult)
- Return type:
list[EdgeExplanation]
- ts2net.fci_algorithm(data, alpha=0.05, variable_names=None, max_conditioning_set=None, ci_method='partial_correlation')[source]
Run the FCI algorithm with partial-correlation CI tests.
FCI extends PC by representing possible latent confounders with circle marks and bidirected arrows in the output PAG.
- Parameters:
data (array (n_samples, n_vars)) – Observations.
alpha (float, default 0.05) – Significance level.
variable_names (list of str, optional) – Variable labels.
max_conditioning_set (int, optional) – Maximum conditioning set size.
ci_method ({"partial_correlation"}) – Conditional independence test.
- Returns:
Partial ancestral graph and separating sets.
- Return type:
Examples
>>> import numpy as np >>> rng = np.random.default_rng(1) >>> lat = rng.standard_normal(1000) >>> x = lat + 0.1 * rng.standard_normal(1000) >>> y = lat + 0.1 * rng.standard_normal(1000) >>> result = fci_algorithm(np.column_stack([x, y]), alpha=0.05) >>> result.pag.number_of_edges() >= 1 True
- ts2net.fci_timeseries_network(X, max_lag=2, alpha=0.05, series_names=None, allow_contemporaneous=True, ci_method='partial_correlation')[source]
FCI discovery on a lag-expanded multivariate time series panel.
- Parameters:
X (list of arrays or array (n_series, n_points)) – Multivariate panel.
max_lag (int, default 2) – Maximum lag order.
alpha (float, default 0.05) – Significance level.
series_names (list of str, optional) – Series labels.
allow_contemporaneous (bool, default True) – Allow contemporaneous edges.
ci_method ({"partial_correlation"}) – CI test.
- Returns:
PAG over lagged variables.
- Return type:
- ts2net.features(series, methods=None, bsts=None, window=None, nvg_limit=None)[source]
Extract features from time series with optional BSTS decomposition.
If BSTS is enabled, decomposes series and analyzes residual with network methods. If BSTS is disabled, analyzes raw series.
- Parameters:
series (array) – Input time series
methods (list of str, optional) – Network methods to apply: ‘hvg’, ‘nvg’, ‘transition’ Default: [‘hvg’, ‘transition’]
bsts (BSTSSpec, optional) – BSTS decomposition specification. If None, analyzes raw series.
window (int, optional) – Window size for windowed analysis. If None, analyzes full series.
nvg_limit (int, optional) – Horizon limit for NVG (default: 3000)
- Returns:
Three blocks: raw_stats, structural_stats, residual_network_stats
- Return type:
Examples
>>> from ts2net.bsts import features, BSTSSpec >>> spec = BSTSSpec(level=True, seasonal_periods=[24, 168]) >>> result = features(x, methods=['hvg', 'transition'], bsts=spec) >>> print(result.structural_stats['seasonal_strength']) >>> print(result.residual_network_stats['hvg']['avg_degree'])
- ts2net.features_to_dataframe(X_features, feature_names, index=None, metadata=None)[source]
Export a feature matrix with stable column names and attrs metadata.
- Parameters:
X_features (array (n_samples, n_features)) – Feature matrix from a ts2net sklearn transformer.
feature_names (sequence of str) – Column names (e.g. from
get_feature_names_out()).index (sequence, optional) – Row index (series ids, timestamps, etc.).
metadata (FeatureMetadata, optional) – Stored in
df.attrs['ts2net'].
- Returns:
Feature table ready for ML pipelines or Parquet export.
- Return type:
pandas.DataFrame
Examples
>>> import numpy as np >>> from ts2net.sklearn import NetworkFeatureExtractor, features_to_dataframe >>> ext = NetworkFeatureExtractor(method="hvg") >>> X = np.random.randn(5, 80) >>> feats = ext.fit_transform(X) >>> df = features_to_dataframe(feats, ext.get_feature_names_out()) >>> df.shape[1] == ext.n_features_out_ True
- ts2net.fit_sindy(X, t, *, x_dot=None, feature_names=None, spec=None)[source]
Fit a SINDy model to multivariate time-series data.
- Parameters:
X (array (n_time, n_coords) or list of such arrays) – State observations. PySINDy axis convention: time first, coordinate second.
t (array, scalar dt, or list of time arrays) – Sample times. Pass scalar
dtwhen the timestep is uniform.x_dot (array, optional) – Known time derivatives (same shape conventions as
X). Rust backend only when supplied via PySINDy fallback.feature_names (list of str, optional) – Names for each coordinate (e.g.
["x", "y"]).spec (SINDySpec, optional) – Model configuration.
spec.backendselectsrust,pysindy, orauto(Rust whents2net_rsis built).
- Returns:
Fitted model, coefficient matrix, and helpers.
- Return type:
- ts2net.from_pandas(df, value_col, group_col=None, time_col=None, sort_by_time=True)[source]
Convert pandas DataFrame to NumPy arrays for ts2net.
- Parameters:
df (pd.DataFrame) – Input DataFrame
value_col (str) – Column name for time series values
group_col (str, optional) – Column name for grouping (e.g., meter_id, region) If provided, returns dict mapping group -> values array
time_col (str, optional) – Column name for timestamps (used for sorting only)
sort_by_time (bool, default True) – If True and time_col provided, sort by time
- Returns:
If group_col is None: single array of values If group_col is provided: dict mapping group -> values array
- Return type:
np.ndarray or dict[str, np.ndarray]
Examples
>>> import pandas as pd >>> df = pd.DataFrame({'timestamp': pd.date_range('2024-01-01', periods=100, freq='1h'), ... 'consumption': np.random.randn(100), ... 'meter_id': ['meter_1'] * 100}) >>> # Single series >>> values = from_pandas(df, value_col='consumption', time_col='timestamp') >>> # Multiple series >>> series = from_pandas(df, value_col='consumption', group_col='meter_id', time_col='timestamp')
- ts2net.from_polars(df, value_col, group_col=None, time_col=None, sort_by_time=True)[source]
Convert polars DataFrame to NumPy arrays for ts2net.
- Parameters:
df (pl.DataFrame) – Input DataFrame
value_col (str) – Column name for time series values
group_col (str, optional) – Column name for grouping (e.g., meter_id, region) If provided, returns dict mapping group -> values array
time_col (str, optional) – Column name for timestamps (used for sorting only)
sort_by_time (bool, default True) – If True and time_col provided, sort by time
- Returns:
If group_col is None: single array of values If group_col is provided: dict mapping group -> values array
- Return type:
np.ndarray or dict[str, np.ndarray]
Examples
>>> import polars as pl >>> df = pl.DataFrame({ ... 'timestamp': pl.datetime_range(pl.date(2024, 1, 1), pl.date(2024, 1, 5), '1h', eager=True), ... 'consumption': np.random.randn(97), ... 'meter_id': ['meter_1'] * 97 ... }) >>> # Single series >>> values = from_polars(df, value_col='consumption', time_col='timestamp') >>> # Multiple series >>> series = from_polars(df, value_col='consumption', group_col='meter_id', time_col='timestamp')
- ts2net.get_performance_contract(method)[source]
Return documented scaling behavior for a builder or API entry point.
- Parameters:
method (str) – Builder or API name (e.g.
hvg,build_windows,ts_dist).- Returns:
Time/memory complexity and usage notes.
- Return type:
- Raises:
KeyError – If no contract is registered for
method.
- ts2net.granger_causality(x, y, max_lag=5, method='linear', test='ssr_ftest', n_permutations=49, random_state=None)[source]
Test whether
xGranger-causesy.- Parameters:
x (array (n,)) – Candidate cause time series.
y (array (n,)) – Effect time series.
max_lag (int, default 5) – Maximum lag order for the autoregressive model.
method ({"linear", "nonlinear"}, default "linear") –
linearuses OLS/VAR F-tests (requires statsmodels).nonlinearuses MLP predictors with permutation testing.test (str, default "ssr_ftest") – statsmodels test name (linear method only).
n_permutations (int, default 49) – Permutation count for nonlinear significance.
random_state (int, optional) – RNG seed for nonlinear method.
- Returns:
Keys:
f_stat,p_value,best_lag,significant. Nonlinear method also returnsmse_improvement.- Return type:
dict
Examples
>>> import numpy as np >>> x = np.random.randn(500) >>> y = np.concatenate([[0], 0.6 * x[:-1] + 0.1 * np.random.randn(499)]) >>> result = granger_causality(x, y, max_lag=3) >>> result["p_value"] < 0.05 True
- ts2net.granger_causality_network(X, max_lag=5, method='linear', alpha=0.05, weight_by='significance', series_names=None, n_jobs=1, test='ssr_ftest', n_permutations=49, random_state=None)[source]
Build a directed Granger-causality network over multiple time series.
Edge
(i, j)means seriesiGranger-causes seriesj.- Parameters:
X (list of arrays or array (n_series, n_points)) – Panel of time series.
max_lag (int, default 5) – Maximum autoregressive lag.
method ({"linear", "nonlinear"}, default "linear") – Granger test variant.
alpha (float, default 0.05) – Significance threshold for retaining edges.
weight_by (str, default "significance") – Edge weight scheme:
p_value(1 - p),f_stat, orsignificance(1 if p < alpha else 0).series_names (list of str, optional) – Node labels.
n_jobs (int, default 1) – Parallel workers for pairwise tests (-1 = all CPUs).
test (str, default "ssr_ftest") – statsmodels test (linear method only).
n_permutations (int, default 49) – Permutations for nonlinear method.
random_state (int, optional) – RNG seed for nonlinear method.
- Returns:
G (networkx.DiGraph) – Directed Granger network.
p_matrix (array (n_series, n_series)) – p-values (p[i, j] = test of i → j).
stats (dict) – Network summary statistics.
- Return type:
Tuple[DiGraph, NDArray, Dict[str, float]]
Examples
>>> import numpy as np >>> x1 = np.random.randn(400) >>> x2 = np.concatenate([[0], 0.5 * x1[:-1] + 0.1 * np.random.randn(399)]) >>> G, p_mat, stats = granger_causality_network([x1, x2], max_lag=3) >>> G.has_edge(0, 1) True
- ts2net.graph_churn(graphs, undirected=True)[source]
Edge churn metrics across a graph sequence.
Returns arrays of length
len(graphs) - 1for births, deaths, and Jaccard similarity between consecutive snapshots.- Parameters:
graphs (list[Graph])
undirected (bool)
- Return type:
dict[str, NDArray[float64]]
- ts2net.graph_summary(G, motifs=None, motif_samples=None, seed=3363)[source]
Compute a comprehensive summary of graph properties.
- Parameters:
G (nx.Graph or nx.DiGraph) – Input graph
motifs (str, optional) – Type of motifs to compute (‘3node’, ‘4node’, or None)
motif_samples (int, optional) – Maximum number of samples for motif counting
seed (int, default 3363) – Random seed for sampling
- Returns:
Dictionary of graph properties
- Return type:
dict
- ts2net.iter_arrow_value_chunks(table, value_col, chunk_size=50000, time_col=None, id_col=None, series_id=None)[source]
Yield value chunks from a PyArrow table without loading the full series.
Accepts
pyarrow.Table,pyarrow.RecordBatch, orpyarrow.RecordBatchReader. Requirespyarrow(included in[pipeline]/[polars]extras).- Parameters:
table (pyarrow Table, RecordBatch, or RecordBatchReader) – Arrow tabular data.
value_col (str) – Numeric value column.
chunk_size (int, default 50_000) – Rows per yielded chunk.
time_col (str, optional) – Sort by this column before chunking.
id_col (str, optional) – Filter to a single series id when set with
series_id.series_id (optional) – Series identifier value when
id_colis provided.
- Yields:
chunk_index (int)
values (array) – Chunk of
value_colas float64.
- Return type:
Iterator[tuple[int, NDArray[float64]]]
- ts2net.iter_parquet_value_chunks(path, value_col, chunk_size=50000, time_col=None, id_col=None, series_id=None)[source]
Yield value chunks from a Parquet file without loading the full series.
Requires the optional
polarspackage (uv sync --extra polars).- Parameters:
path (str or Path) – Parquet file or directory.
value_col (str) – Numeric value column.
chunk_size (int, default 50_000) – Rows per yielded chunk.
time_col (str, optional) – Sort by this column before chunking.
id_col (str, optional) – Filter to a single series id when set with
series_id.series_id (str, optional) – Series identifier value when
id_colis provided.
- Yields:
chunk_index (int)
values (array) – Chunk of
value_colas float64.
- Return type:
Iterator[tuple[int, NDArray[float64]]]
- ts2net.iter_series_chunks(x, chunk_size, overlap=0, dtype=<class 'numpy.float64'>)[source]
Iterate over contiguous chunks of a series or memory-mapped file.
- Parameters:
x (array or path) – In-memory series or path to a binary/memmap file.
chunk_size (int) – Points per chunk.
overlap (int, default 0) – Overlap between consecutive chunks.
dtype (numpy dtype, default float64) – Dtype when loading from file.
- Yields:
chunk_index (int)
chunk (array)
- Return type:
Iterator[tuple[int, NDArray[float64]]]
- ts2net.iter_windows(x, width, step=1, start=0, end=None, copy=False)[source]
Yield sliding windows without materializing the full window matrix.
- Parameters:
x (array (n_points,)) – Input time series.
width (int) – Window width.
step (int, default 1) – Step between consecutive windows.
start (int, optional) – Slice bounds on
x(same semantics asts_to_windows).end (int, optional) – Slice bounds on
x(same semantics asts_to_windows).copy (bool, default False) – If True, copy each window slice (safer if
xis mutated).
- Yields:
window_index (int) – Zero-based window index.
start_index (int) – Start position in
x.window (array (width,)) – Window values.
- Return type:
Iterator[tuple[int, int, NDArray[float64]]]
- ts2net.list_performance_contracts()[source]
Return all registered performance contracts.
- Return type:
dict[str, PerformanceContract]
- ts2net.load_series_from_parquet_polars(path, time_col, value_col, id_col=None, start=None, end=None, freq=None, agg='mean', tz=None, columns_extra=None)[source]
Load time series from Parquet file using Polars (lazy evaluation).
Uses lazy evaluation to minimize memory usage. Converts to NumPy arrays for compatibility with ts2net core algorithms.
- Parameters:
path (str) – Path to Parquet file or directory of Parquet files
time_col (str) – Column name for timestamps
value_col (str) – Column name for values
id_col (str, optional) – Column name for series identifier (e.g., meter_id, region) If None, returns single series as tuple (times, values)
start (str, optional) – Start timestamp filter (ISO format or parseable by Polars)
end (str, optional) – End timestamp filter (ISO format or parseable by Polars)
freq (str, optional) – Time frequency for bucketing (e.g., ‘1h’, ‘1d’, ‘15m’) Uses Polars group_by_dynamic for efficient time-based aggregation
agg (str, default 'mean') – Aggregation function: ‘mean’, ‘sum’, ‘min’, ‘max’, ‘median’, ‘first’, ‘last’
tz (str, optional) – Timezone for time_col (e.g., ‘UTC’, ‘Europe/Madrid’)
columns_extra (list[str], optional) – Additional columns to keep in output (not used for aggregation)
- Returns:
If id_col is provided: dict mapping id -> values array If id_col is None: tuple of (times, values) arrays
- Return type:
dict[str, np.ndarray] or tuple[np.ndarray, np.ndarray]
Examples
>>> # Single series >>> times, values = load_series_from_parquet_polars( ... 'data.parquet', time_col='timestamp', value_col='consumption' ... )
>>> # Multiple series by meter_id >>> series = load_series_from_parquet_polars( ... 'data.parquet', ... time_col='timestamp', ... value_col='consumption', ... id_col='meter_id', ... freq='1h', ... start='2024-01-01', ... end='2024-12-31' ... ) >>> # series = {'meter_1': np.array([...]), 'meter_2': np.array([...]), ...}
- ts2net.multiplex_graph(layers)[source]
Create a multiplex graph from a dictionary of layers.
- Parameters:
layers (dict[str, Graph])
- Return type:
- ts2net.multiplex_visibility_graph(x, *, hvg_kwargs=None, nvg_kwargs=None)[source]
Build HVG and NVG layers over the same series.
- Parameters:
x (array (n,)) – Input time series.
hvg_kwargs (dict, optional) – Arguments passed to
HVG/NVGbuilders.nvg_kwargs (dict, optional) – Arguments passed to
HVG/NVGbuilders.
- Returns:
multiplex (MultiplexGraph) – Layers
"hvg"and"nvg".layers (dict) – Raw NetworkX graphs per layer.
- Return type:
tuple[MultiplexGraph, dict[str, Graph]]
- ts2net.node_role_evolution(graphs, **role_kwargs)[source]
Track node role labels across a graph sequence.
- Returns:
Node id -> list of roles (one per window;
Noneif absent).- Return type:
dict
- Parameters:
graphs (list[Graph])
- ts2net.node_roles(G, hub_quantile=0.9, isolate_max_degree=0)[source]
Classify nodes by degree and betweenness centrality.
- Parameters:
G (networkx.Graph) – Graph snapshot.
hub_quantile (float, default 0.9) – Degree quantile above which a node is a hub.
isolate_max_degree (int, default 0) – Maximum degree for isolate classification.
- Returns:
Node id -> role label.
- Return type:
dict
- ts2net.partial_correlation_matrix(X)[source]
Partial correlation matrix for a multivariate panel.
Uses the precision matrix formulation (requires
n_points > n_series).
- ts2net.partial_correlation_network(X, rule='knn', k=5, threshold=0.3, epsilon=0.5, weighted=True)[source]
Gaussian graphical-model style network from partial correlations.
- Parameters:
rule (Literal['knn', 'epsilon', 'threshold', 'complete']) – Same sparsification options as
correlation_network.k (int) – Same sparsification options as
correlation_network.threshold (float) – Same sparsification options as
correlation_network.epsilon (float) – Same sparsification options as
correlation_network.weighted (bool) – Same sparsification options as
correlation_network.
- Returns:
G (networkx.Graph)
P (partial correlation matrix)
D (distance matrix (1 - |P|))
- Return type:
tuple[Graph, NDArray[float64], NDArray[float64]]
- ts2net.pc_algorithm(data, alpha=0.05, variable_names=None, max_conditioning_set=None, ci_method='partial_correlation')[source]
Run the PC algorithm with partial-correlation CI tests.
- Parameters:
data (array (n_samples, n_vars)) – Observations (rows = samples).
alpha (float, default 0.05) – Significance level for conditional independence tests.
variable_names (list of str, optional) – Labels for each column.
max_conditioning_set (int, optional) – Maximum conditioning set size (default: number of variables - 2).
ci_method ({"partial_correlation"}, default "partial_correlation") – Conditional independence test.
- Returns:
Skeleton, separating sets, and oriented CPDAG.
- Return type:
Examples
>>> import numpy as np >>> rng = np.random.default_rng(0) >>> x = rng.standard_normal(800) >>> y = 0.8 * x + 0.1 * rng.standard_normal(800) >>> z = 0.8 * y + 0.1 * rng.standard_normal(800) >>> result = pc_algorithm(np.column_stack([x, y, z]), alpha=0.01) >>> result.cpdag.number_of_edges() >= 2 True
- ts2net.pc_timeseries_network(X, max_lag=2, alpha=0.05, series_names=None, allow_contemporaneous=True, ci_method='partial_correlation')[source]
PC discovery on a lag-expanded multivariate time series panel.
Time-aware filtering removes edges that violate temporal ordering (cause must not be more recent than effect).
- Parameters:
X (list of arrays or array (n_series, n_points)) – Multivariate panel.
max_lag (int, default 2) – Maximum lag order for variable expansion.
alpha (float, default 0.05) – Significance level.
series_names (list of str, optional) – Series labels.
allow_contemporaneous (bool, default True) – Allow edges among variables at the same time slice.
ci_method ({"partial_correlation"}) – Conditional independence test.
- Returns:
CPDAG over lagged variables.
- Return type:
- ts2net.plot_degree_ccdf(degrees, title=None, figsize=None)[source]
Figure 3: Degree distribution as CCDF (Complementary CDF).
Plots the complementary CDF of degrees on log y scale. Works better than a histogram, stays stable across sample size, makes cross-zone comparison easy.
- Parameters:
degrees (array (n,)) – Degree sequence
title (str, optional) – Plot title
figsize (tuple, optional) – Figure size (default: (10, 6))
- Returns:
fig (matplotlib.figure.Figure)
ax (matplotlib.axes.Axes)
- Return type:
Tuple[Figure, Axes]
- ts2net.plot_degree_profile(degrees, time_index=None, title=None, figsize=None)[source]
Figure 2: Degree profile across time.
Plots degree versus time index. This becomes a direct proxy for “local complexity” in the signal. Reads well and scales well.
- Parameters:
degrees (array (n,)) – Degree sequence (one per node/time point)
time_index (array (n,), optional) – Time indices (default: 0, 1, 2, …)
title (str, optional) – Plot title
figsize (tuple, optional) – Figure size (default: (10, 6))
- Returns:
fig (matplotlib.figure.Figure)
ax (matplotlib.axes.Axes)
- Return type:
Tuple[Figure, Axes]
- ts2net.plot_hvg_small(x, edges, time_index=None, title=None, figsize=None)[source]
Optional: Small n graph drawing for HVG.
Uses fixed layout based on time index. Nodes at x = time, y = normalized value. Edges drawn as faint arcs or straight lines. Shows visibility logic.
- Parameters:
x (array (n,)) – Time series values
edges (list of tuples) – Edge list [(i, j), …]
time_index (array (n,), optional) – Time indices (default: 0, 1, 2, …)
title (str, optional) – Plot title
figsize (tuple, optional) – Figure size (default: (10, 6))
- Returns:
fig (matplotlib.figure.Figure)
ax (matplotlib.axes.Axes)
- Return type:
Tuple[Figure, Axes]
- ts2net.plot_method_comparison(df_metrics, methods=None, figsize=None)[source]
Figure 4: Method comparison panel.
Creates a small table graphic with three aligned dot plots: - Edge count - Average degree - Normalized density (edges / n)
Uses one axis per metric. Zones/methods on y-axis.
- Parameters:
df_metrics (dict or array) – Dictionary mapping method names to dicts with ‘n_edges’, ‘avg_degree’, ‘density’ OR array of dicts with ‘method’ key
methods (list of str, optional) – Method names (if df_metrics is array)
figsize (tuple, optional) – Figure size (default: (12, 6))
- Returns:
fig (matplotlib.figure.Figure)
axes (list of matplotlib.axes.Axes)
- Return type:
Tuple[Figure, List[Axes]]
- ts2net.plot_recurrence_matrix(recurrence_matrix, title=None, figsize=None)[source]
Optional: Recurrence plot style view for recurrence networks.
Draws the recurrence matrix as an image for a short window. Users already understand this visual.
- Parameters:
recurrence_matrix (array (n, n)) – Recurrence/adjacency matrix
title (str, optional) – Plot title
figsize (tuple, optional) – Figure size (default: (8, 8))
- Returns:
fig (matplotlib.figure.Figure)
ax (matplotlib.axes.Axes)
- Return type:
Tuple[Figure, Axes]
- ts2net.plot_series_with_events(x, events=None, window=None, window_bounds=None, time_index=None, title=None, figsize=None)[source]
Figure 1: Time series with change points and window boundaries.
Shows the signal with detected change points as thin vertical lines and window edges as faint bands. Provides context for network results.
- Parameters:
x (array (n,)) – Time series values
events (array (m,), optional) – Indices of detected change points
window (tuple (start, end), optional) – Single window boundaries to highlight
window_bounds (list of tuples, optional) – Multiple window boundaries [(start, end), …]
time_index (array (n,), optional) – Time indices (default: 0, 1, 2, …)
title (str, optional) – Plot title
figsize (tuple, optional) – Figure size (default: (10, 6))
- Returns:
fig (matplotlib.figure.Figure)
ax (matplotlib.axes.Axes)
- Return type:
Tuple[Figure, Axes]
- ts2net.plot_window_feature_map(df_window_features, feature_names=None, time_labels=None, figsize=None)[source]
Figure 5: Window level feature map.
Computes window stats (mean degree, degree variance, assortativity proxy, transition entropy) and plots as a heatmap with time on x and feature on y. Provides anomaly signatures.
- Parameters:
df_window_features (dict or array) – Dictionary mapping feature names to arrays OR array of dicts
feature_names (list of str, optional) – Feature names (if df_window_features is dict, uses keys)
time_labels (list of str, optional) – Time window labels (default: 0, 1, 2, …)
figsize (tuple, optional) – Figure size (default: (12, 8))
- Returns:
fig (matplotlib.figure.Figure)
ax (matplotlib.axes.Axes)
- Return type:
Tuple[Figure, Axes]
- ts2net.recurrence_matrix(x, epsilon=None, target_density=0.05)[source]
Boolean recurrence matrix for a univariate series.
- Parameters:
x (array (n,))
epsilon (float, optional) – Distance threshold; chosen from
target_densityif None.target_density (float)
- Return type:
NDArray[bool]
- ts2net.recurrence_quantification(x, epsilon=None, target_density=0.05, m=None, tau=1, lmin=2, vmin=2, output='edges')[source]
Recurrence network plus RQA (recurrence quantification analysis) metrics.
- Parameters:
x (array (n,)) – Input series.
epsilon (float, optional) – Recurrence threshold.
target_density (float) – Used to pick
epsilonwhen not provided.m (int) – Embedding parameters passed to the recurrence builder.
tau (int) – Embedding parameters passed to the recurrence builder.
lmin (int) – Minimum diagonal / vertical line lengths for RQA.
vmin (int) – Minimum diagonal / vertical line lengths for RQA.
output (str) – Builder output mode.
- Returns:
Keys:
epsilon,rqa,recurrence_rate,builder,matrix.rqacontains RR, DET, L, Lmax, ENTR, LAM, TT.- Return type:
dict
- ts2net.rolling_correlation_matrix(x, y, window, step=1, method='pearson')[source]
Rolling window correlation between two aligned series.
- Returns:
values (array (n_windows,))
centers (array (n_windows,) window center indices)
- Parameters:
x (NDArray[float64])
y (NDArray[float64])
window (int)
step (int)
method (Literal['pearson', 'spearman', 'kendall', 'dcor'])
- Return type:
tuple[NDArray[float64], NDArray[int64]]
- ts2net.rolling_correlation_network(X, window, step=1, method='pearson', rule='knn', k=3, threshold=0.5)[source]
Sequence of correlation networks over rolling windows.
Each window uses all series segments
X[:, t:t+window].- Parameters:
X (NDArray[float64])
window (int)
step (int)
method (Literal['pearson', 'spearman', 'kendall', 'dcor'])
rule (Literal['knn', 'epsilon', 'threshold', 'complete'])
k (int)
threshold (float)
- Return type:
list[tuple[Graph, NDArray[float64]]]
- ts2net.run_causal_analysis(X, spec=None, **kwargs)[source]
Run a full causal network workflow on a multivariate time series panel.
Steps: 1. Optional lag search per edge (Granger AIC/p-value or TE maximum) 2. Pairwise causal tests with significance / permutation confidence 3. Optional confounder adjustment (partial Granger or conditional TE) 4. Network construction and topology metrics 5. Plain-language summary via
CausalAnalysisResult.summary()- Parameters:
X (list of arrays or array (n_series, n_points)) – Multivariate time series panel.
spec (CausalWorkflowSpec, optional) – Workflow configuration. Extra
**kwargsoverride spec fields.**kwargs – Override any
CausalWorkflowSpecfield by name.
- Returns:
Graph, edge table, matrices, metrics, and report helpers.
- Return type:
Examples
>>> import numpy as np >>> rng = np.random.default_rng(0) >>> x1 = rng.standard_normal(400) >>> x2 = np.concatenate([[0], 0.6 * x1[:-1] + 0.05 * rng.standard_normal(399)]) >>> result = run_causal_analysis([x1, x2], method="granger", lag_search=True) >>> print(result.summary())
- ts2net.run_dynamic_analysis(x, spec=None, **kwargs)[source]
Run dynamic network analysis on a univariate time series.
Steps: 1. Build rolling graph sequence 2. Detect regime changes in a chosen graph metric 3. Score window-level and transition-level anomalies 4. Track edge persistence, communities, and node roles 5. Attribute metric shifts at detected breaks
- Parameters:
x (array (n_points,)) – Input time series.
spec (DynamicWorkflowSpec, optional) – Workflow configuration. Extra
**kwargsoverride spec fields.**kwargs – Override any
DynamicWorkflowSpecfield by name.
- Returns:
Sequence, metrics, and report helpers.
- Return type:
Examples
>>> import numpy as np >>> rng = np.random.default_rng(0) >>> x = rng.standard_normal(500) >>> x[250:] += 3.0 # regime shift >>> result = run_dynamic_analysis(x, window=40, step=20) >>> print(result.summary())
- ts2net.sax_symbolize(x, n_bins=8, word_size=3)[source]
Symbolic Aggregate approXimation (SAX) of a time series.
- Parameters:
x (array (n,))
n_bins (int) – Alphabet size.
word_size (int) – PAA segment size (series length should be divisible).
- Returns:
symbols – Integer symbols per SAX word.
- Return type:
array (n_words,)
- ts2net.sax_transition_network(x, n_bins=8, word_size=3, output='edges')[source]
Build a transition network on SAX symbols.
Uses equal-width transitions between consecutive SAX words mapped to ordinal symbols, via
TransitionNetwork(symbolizer='equal_freq')on the SAX symbol sequence.- Returns:
builder (TransitionNetwork)
symbols (SAX symbol sequence)
- Parameters:
x (NDArray[float64])
n_bins (int)
word_size (int)
output (str)
- Return type:
tuple[TransitionNetwork, NDArray[int32]]
- ts2net.search_granger_lag(x, y, max_lag=10, criterion='pvalue', test='ssr_ftest')[source]
Select the best Granger lag order for
x→y.- Parameters:
x (array (n,)) – Cause and effect time series.
y (array (n,)) – Cause and effect time series.
max_lag (int, default 10) – Maximum lag to evaluate.
criterion ({"pvalue", "aic", "bic"}, default "pvalue") –
pvaluepicks the lag with the smallest p-value.aic/bicpick the lag with the lowest information criterion from the unrestricted AR model.test (str, default "ssr_ftest") – statsmodels Granger test name.
- Returns:
best_lag (int) – Selected lag order.
scores (dict) – Per-lag statistics (
p_value,f_stat, and optionallyaic/bic).
- Return type:
Tuple[int, Dict[int, Dict[str, float]]]
- ts2net.search_te_lag(x, y, lags=None, bins=10, method='discrete')[source]
Select the lag with maximum transfer entropy from
xtoy.- Parameters:
x (array (n,)) – Source and target time series.
y (array (n,)) – Source and target time series.
lags (list of int, optional) – Candidate lags (default
[1, 2, 3, 5, 10]capped by series length).bins (int, default 10) – Discretization bins for discrete TE.
method ({"discrete", "knn"}, default "discrete") – Transfer entropy estimator.
- Returns:
best_lag (int) – Lag with highest TE.
scores (dict) – Transfer entropy at each evaluated lag.
- Return type:
Tuple[int, Dict[int, float]]
- ts2net.should_use_approximate(n_series, approximate, threshold)[source]
Return whether approximate kNN is recommended.
- Parameters:
n_series (int)
approximate (bool)
threshold (int)
- Return type:
bool
- ts2net.similarity_matrix(X, method='correlation', n_jobs=1, **kwargs)[source]
Pairwise dissimilarity matrix between time series.
- ts2net.similarity_network(X, method='correlation', rule='knn', k=5, epsilon=0.3, threshold=None, n_jobs=1, weighted=True, approximate=False, approx_threshold=500, **kwargs)[source]
Build a similarity network from a panel of time series.
- Parameters:
method (str) – Distance/similarity measure.
rule ({"knn", "epsilon", "threshold", "complete"})
k (int) – Sparsification parameters.
epsilon (float) – Sparsification parameters.
threshold (float | None) – Sparsification parameters.
n_jobs (int) – Parallel workers for distance computation.
weighted (bool) – Edge weights = dissimilarity values.
approximate (bool, default False) – Use pynndescent approximate k-NN when
rule='knn'.approx_threshold (int, default 500) – Auto-enable approximate k-NN when
n_series >= approx_threshold.
- Returns:
G (networkx.Graph)
D (distance matrix)
- Return type:
tuple[Graph, NDArray[float64]]
- ts2net.sindy_coupling_network(result, *, threshold=0.05, linear_only=True, include_self=False)[source]
Build a directed coupling graph from SINDy coefficients.
Nodes are state variables. An edge
j → iis added when the discovered equation forstate_ihas a term involvingstate_jabovethreshold.For a first-order polynomial library, off-diagonal linear terms correspond to direct couplings in
ẋ = Ξ Θ(x).- Parameters:
result (SINDyResult) – Output of
fit_sindy().threshold (float) – Minimum |coefficient| to keep an edge.
linear_only (bool, default True) – If True, only use pure state features (ignore
x*y,x^2, etc.).include_self (bool, default False) – Include diagonal self-dynamics as self-loops.
- Returns:
Edge attribute
weightholds the SINDy coefficient.- Return type:
networkx.DiGraph
- ts2net.sindy_jacobian_network(result, x_eq=None, *, threshold=0.05)[source]
Linearization graph: evaluate Jacobian of the discovered field at
x_eq.Defaults to the origin when
x_eqis None (appropriate for polynomial models when linear couplings dominate near zero).- Parameters:
result (SINDyResult)
x_eq (ndarray | None)
threshold (float)
- Return type:
DiGraph
- ts2net.statistical_baseline_features(X)[source]
Classical time-series statistics as a baseline feature set.
Per series: mean, std, skew, kurtosis, lag-1 autocorrelation, trend slope, and zero-crossing rate.
- Parameters:
X (array (n_series, n_timesteps)) – Panel of univariate time series.
- Returns:
features (array (n_series, n_features))
names (list of str) – Stable feature names.
- Return type:
tuple[NDArray[float64], list[str]]
- ts2net.stream_chunk_stats(source, chunk_size, method='hvg', overlap=0, value_col=None, time_col=None, id_col=None, series_id=None, **method_kwargs)[source]
Compute graph summary stats on contiguous chunks (memmap-safe).
- Parameters:
source (array, path, Parquet path, or pyarrow Table) – In-memory series, memmap file, Parquet file/directory, or Arrow table.
chunk_size (int) – Points per chunk.
method (str, default "hvg") – Builder name:
hvg,nvg,recurrence,transition.overlap (int, default 0) – Overlap between chunks for in-memory/memmap sources only.
value_col (str, optional) – Required when
sourceis Parquet or Arrow tabular data.time_col (optional) – Column filtering/sorting for Parquet and Arrow sources.
id_col (optional) – Column filtering/sorting for Parquet and Arrow sources.
series_id (optional) – Column filtering/sorting for Parquet and Arrow sources.
**method_kwargs – Passed to the graph builder config (including
backend=).
- Yields:
chunk_index (int)
stats (dict) – Graph summary for the chunk.
- Return type:
Iterator[tuple[int, dict[str, float]]]
- ts2net.temporal_cnn_embeddings(x, window, stride, *, channels=(32, 64, 64), kernel_size=5, dilations=(1, 2, 4), dropout=0.1, device='cpu', batch_size=256, seed=7)[source]
Compute per-window embeddings with a small dilated 1D CNN.
- Parameters:
x (NDArray[float64]) – Array of shape (n, f) or (n,). For multivariate, f is number of features.
window (int) – Window length in time steps.
stride (int) – Step between windows.
channels (Tuple[int, ...]) – Output channels per conv block. Length must match dilations.
kernel_size (int) – Kernel size for each conv.
dilations (Tuple[int, ...]) – Dilation per block. Length must match channels length.
dropout (float) – Dropout rate.
device (str) – Torch device string (‘cpu’ or ‘cuda’).
batch_size (int) – Batch size for inference.
seed (int) – Random seed for determinism.
- Returns:
Array of shape (n_windows, channels[-1]) with embeddings.
- Raises:
ImportError – If PyTorch is not installed.
ValueError – If input shape is invalid or parameters don’t match.
- Return type:
NDArray[float64]
- ts2net.time_lagged_causality_network(X, lags=None, method='transfer_entropy', combine='per_lag', n_jobs=1, **kwargs)[source]
Analyze causal structure at multiple time lags.
- Parameters:
X (list of arrays or array (n_series, n_points)) – Panel of time series.
lags (list of int, optional) – Lags to evaluate (default
[1, 2, 3, 5]).method ({"transfer_entropy", "granger"}, default "transfer_entropy") – Causality measure.
combine ({"per_lag", "max", "mean"}, default "per_lag") –
per_lagreturns a dict keyed by lag.max/meanaggregate the weight matrices across lags.n_jobs (int, default 1) – Parallel workers passed to the underlying network builder.
**kwargs – Extra arguments for
transfer_entropy_networkorgranger_causality_network(e.g.bins,alpha,max_lag).
- Returns:
per_lag (dict[int, (G, matrix, stats)]) – When
combine="per_lag".G, matrix, stats (tuple) – Combined network when
combineismaxormean.
- Return type:
Dict[int, Tuple[DiGraph, NDArray, Dict[str, float]]] | Tuple[DiGraph, NDArray, Dict[str, float]]
Examples
>>> import numpy as np >>> X = [np.random.randn(300) for _ in range(3)] >>> results = time_lagged_causality_network(X, lags=[1, 2], method="transfer_entropy") >>> 1 in results and 2 in results True
- ts2net.to_dgl_graph(graph, node_features=None, feature_name='feat', weight_name='weight')[source]
Convert a
Graphto a DGL graph.- Parameters:
graph (Graph) – ts2net graph (integer node indices recommended).
node_features (array (n_nodes, n_features), optional) – Stored in
g.ndata[feature_name]. Defaults to degree features.feature_name (str, default "feat") – Node data field name.
weight_name (str, default "weight") – Edge weight field name.
- Return type:
dgl.DGLGraph
Examples
>>> import numpy as np >>> from ts2net import HVG >>> from ts2net.ml import to_dgl_graph >>> hvg = HVG().build(np.random.randn(50)) >>> g = to_dgl_graph(hvg._graph)
- ts2net.to_pyg_data(graph, node_features=None, y=None, graph_label=None)[source]
Convert a
Graphto a PyGDataobject.- Parameters:
- Returns:
PyG graph with
x,edge_index, optionaledge_attr,y.- Return type:
torch_geometric.data.Data
Examples
>>> import numpy as np >>> from ts2net import HVG >>> from ts2net.ml import to_pyg_data >>> hvg = HVG().build(np.random.randn(50)) >>> data = to_pyg_data(hvg._graph)
- ts2net.to_sparse_csr(graph, dtype=<class 'numpy.float64'>)[source]
Return a CSR adjacency matrix without densifying.
- Parameters:
graph (Graph) – ts2net graph result.
dtype (numpy dtype, default float64) – Matrix value dtype.
- Returns:
Sparse adjacency of shape (n_nodes, n_nodes).
- Return type:
scipy.sparse.csr_matrix
- ts2net.track_communities(graphs)[source]
Track community structure across graph windows.
- Returns:
labels_per_window(list of node->community dicts),n_communities(array),stability(mean Jaccard overlap of consecutive community partitions).- Return type:
dict
- Parameters:
graphs (list[Graph])
- ts2net.transfer_entropy(x, y, lag=1, bins=10, method='discrete')[source]
Compute transfer entropy from X to Y.
Transfer entropy measures the amount of information transferred from X to Y, quantifying causal influence. TE(X→Y) = H(Y_t | Y_{t-1}) - H(Y_t | Y_{t-1}, X_{t-1}).
- Parameters:
x (array (n,)) – Source time series
y (array (n,)) – Target time series (must have same length as x)
lag (int, default 1) – Time lag for past values
bins (int, default 10) – Number of bins for discretization (only used if method=”discrete”)
method (str, default "discrete") – Method for computing entropy: “discrete” (binning) or “knn” (k-nearest neighbors)
- Returns:
te – Transfer entropy from X to Y (non-negative, bits)
- Return type:
float
Examples
>>> import numpy as np >>> x = np.random.randn(1000) >>> y = x[:-1] + 0.1 * np.random.randn(999) # y depends on x >>> y = np.concatenate([[0], y]) # Pad to same length >>> te = transfer_entropy(x, y, lag=1) >>> print(f"Transfer entropy X→Y: {te:.4f} bits")
- ts2net.transfer_entropy_network(X, lag=1, bins=10, threshold=None, method='discrete', series_names=None, n_jobs=1)[source]
Construct a directed network based on transfer entropy between time series.
Each edge (i, j) represents causal influence from series i to series j, weighted by the transfer entropy value.
- Parameters:
X (list of arrays or array (n_series, n_points)) – Multiple time series to analyze
lag (int, default 1) – Time lag for transfer entropy computation
bins (int, default 10) – Number of bins for discretization (only used if method=”discrete”)
threshold (float, optional) – Minimum transfer entropy threshold for edges (if None, include all edges)
method (str, default "discrete") – Method for computing entropy: “discrete” or “knn”
series_names (list of str, optional) – Names for each series (default: “Series_0”, “Series_1”, …)
n_jobs (int, default 1) – Parallel workers for pairwise transfer entropy (-1 = all CPUs).
- Returns:
G (networkx.DiGraph) – Directed network with transfer entropy as edge weights
te_matrix (array (n_series, n_series)) – Transfer entropy matrix (TE[i, j] = TE from series i to series j)
stats (dict) – Network statistics including mean TE, max TE, etc.
- Return type:
Tuple[DiGraph, NDArray, Dict[str, float]]
Examples
>>> import numpy as np >>> X = [np.random.randn(1000) for _ in range(5)] >>> G, te_matrix, stats = transfer_entropy_network(X, lag=1, threshold=0.1) >>> print(f"Network: {G.number_of_nodes()} nodes, {G.number_of_edges()} edges") >>> print(f"Mean transfer entropy: {stats['mean_te']:.4f} bits")
- ts2net.visibility_irreversibility(x, weighted=False, limit=None)[source]
Scalar irreversibility score from a directed HVG.
- Parameters:
x (array (n,)) – Input time series.
weighted (bool, default False) – Use absolute-difference edge weights.
limit (int, optional) – Maximum temporal distance between connected nodes.
- Returns:
Mean node-level |in_degree - out_degree| / total_degree in [0, 1].
- Return type:
float
- ts2net.window_anomaly_scores(stats, metrics=None)[source]
Per-window anomaly score from graph summary statistics.
Uses the maximum absolute z-score across selected metrics at each window.
- Parameters:
stats (dict[str, array]) – Window-level stats (e.g. from
RollingGraphSequence.statsorbuild_windowsoutput).metrics (list of str, optional) – Metrics to include. Defaults to numeric keys with length > 2.
- Returns:
Anomaly score per window (higher = more unusual).
- Return type:
array (n_windows,)
Graph Builders
ts2net public API — four graph builders and a factory function.
Primary interface: builder.build(x) — builds and returns self.
Sklearn interface: builder.fit_transform(x) — returns NetworkX graph.
Split interface: builder.fit(x).transform() — deprecated; prefer build().
- All builders share the same output methods after build():
.n_nodes int .n_edges int .degree_sequence() NDArray[int64] .adjacency_matrix() sparse CSR (default) or dense .stats() dict of summary metrics .as_networkx() nx.Graph (optional; large graphs refused unless force=True)
- class ts2net.api.HVG(weighted=False, limit=None, only_degrees=False, output='edges', directed=False, weight_mode=None)[source]
Bases:
SklearnBuildMixinHorizontal Visibility Graph (HVG).
Two nodes i < j are connected if every intermediate value is strictly below the lower of the two endpoints:
x[k] < min(x[i], x[j]) for all i < k < j
Complexity: O(n) time and space (monotone stack algorithm).
Key invariants (random i.i.d. series): - Mean degree → 4 as n → ∞ (Luque et al. 2009) - Degree distribution follows P(k) ~ (1/3)(2/3)^(k-2) for k ≥ 2
- Parameters:
weighted (bool) – Edge weights = abs(y_i - y_j)
limit (int, optional) – Maximum temporal distance between connected nodes.
Nonemeans unconstrained (default). Useful for very long series where distant connections are not meaningful.output ({"edges", "degrees", "stats"}, default "edges") –
"edges"stores the full edge list;"degrees"stores only the degree sequence (fast, low memory);"stats"stores only summary statistics (lowest memory).directed (bool, default False) – Produce a directed graph with edges pointing forward in time (i → j for i < j). Enables irreversibility analysis.
only_degrees (bool)
weight_mode (str | None)
References
Luque, B., Lacasa, L., Ballesteros, F., & Luque, J. (2009). Horizontal visibility graphs: Exact results for random time series. Physical Review E, 80(4), 046103. https://doi.org/10.1103/PhysRevE.80.046103
Examples
>>> import numpy as np >>> from ts2net import HVG >>> x = np.random.randn(1000) >>> hvg = HVG().build(x) # build() returns self for chaining >>> print(hvg.n_nodes, hvg.n_edges) >>> degrees = hvg.degree_sequence >>> A = hvg.adjacency_matrix() # sparse CSR by default >>> G_nx = hvg.as_networkx() # Optional
- adjacency_matrix(format='sparse')[source]
Adjacency matrix.
- Parameters:
format ({"sparse", "coo", "dense"}, default "sparse") –
"sparse"returns a SciPy CSR matrix."coo"returns a SciPy COO matrix."dense"returns a NumPy array; refused for n > 50 000 nodes (would require ≥ 20 GB RAM).- Returns:
A – Symmetric adjacency matrix of shape (n_nodes, n_nodes).
- Return type:
csr_matrix | coo_matrix | ndarray
- as_networkx(force=False)[source]
Convert to a NetworkX graph.
- Parameters:
force (bool, default False) – If False, raises for n > 200 000 nodes to prevent accidental allocation of very large objects.
- Returns:
G
- Return type:
nx.Graph or nx.DiGraph
- build(x)[source]
Build HVG from time series.
Equivalent to
fit(x); returnsselffor method chaining.- Parameters:
x (array-like of shape (n,)) – Input time series.
- Returns:
self
- Return type:
- degree_sequence()[source]
Node degree sequence.
- Returns:
d – Out-degree for directed graphs; total degree for undirected.
- Return type:
NDArray[int64] of shape (n_nodes,)
- property edges
Edge list (None if output=’degrees’ or ‘stats’)
- edges_coo()[source]
Edge list in COO (coordinate) format.
- Returns:
rows (NDArray[int64] — source node indices)
cols (NDArray[int64] — target node indices)
weights (NDArray[float64] or None — edge weights (None if unweighted))
- Return type:
Tuple[NDArray[int64], NDArray[int64], NDArray[float64] | None]
- fit(x)
Store and validate input; does not build until transform().
- Parameters:
x (NDArray[float64])
- Return type:
SklearnBuildMixin
- fit_transform(x)
Fit and transform in one step.
- Parameters:
x (NDArray[float64])
- Return type:
Graph
- property n_edges
Number of edges
- property n_nodes
Number of nodes
- network_metrics(include=None, sample_size=None, **kwargs)[source]
Compute advanced network metrics (clustering, path lengths, modularity).
- Parameters:
include (list, optional) – Metrics to include: [“clustering”, “path_lengths”, “modularity”] If None, includes all metrics
sample_size (int, optional) – For large graphs, sample nodes/pairs for expensive computations
**kwargs – Additional arguments passed to metric functions (e.g., method, weight, resolution, seed)
- Returns:
Dictionary with network metrics: - Clustering: avg_clustering, transitivity - Path lengths: avg_path_length, diameter, radius - Modularity: modularity, n_communities
- Return type:
dict
Examples
>>> from ts2net import HVG >>> import numpy as np >>> x = np.random.randn(100) >>> hvg = HVG() >>> hvg.build(x) >>> metrics = hvg.network_metrics() >>> print(f"Clustering: {metrics['avg_clustering']:.3f}") >>> print(f"Avg path length: {metrics['avg_path_length']:.3f}") >>> print(f"Modularity: {metrics['modularity']:.3f}")
- stats(include_triangles=False)[source]
Summary statistics (memory efficient, no dense matrix)
- Parameters:
include_triangles (bool)
- Return type:
dict
- test_significance(metric='density', method='shuffle', n_surrogates=200, alpha=0.05, rng=None, **kwargs)[source]
Test significance of a network metric against null distribution.
- Parameters:
metric (str, default "density") – Metric to test. Options: “density”, “deg_mean”, “deg_std”, “avg_clustering”, “assortativity”, or any key from stats()
method (str, default "shuffle") – Surrogate generation method: “shuffle”, “phase”, “circular”, “iaaft”, “block_bootstrap”
n_surrogates (int, default 200) – Number of surrogate series to generate
alpha (float, default 0.05) – Significance level (two-tailed)
rng (np.random.Generator, optional) – Random number generator
**kwargs – Additional arguments for surrogate generation (e.g., block_size for block_bootstrap)
- Returns:
result – Significance test result
- Return type:
NetworkSignificanceResult
Examples
>>> from ts2net import HVG >>> import numpy as np >>> x = np.random.randn(100) >>> hvg = HVG() >>> hvg.build(x) >>> result = hvg.test_significance(metric="density", method="phase", n_surrogates=100) >>> print(result)
- transform()
Build the network from data stored by fit().
- Return type:
Graph
- class ts2net.api.NVG(weighted=False, limit=None, only_degrees=False, output='edges', max_edges=None, max_edges_per_node=None, max_memory_mb=None, weight_mode=None)[source]
Bases:
SklearnBuildMixinNatural Visibility Graph (NVG).
Two nodes i < j are connected if the straight line between (i, x[i]) and (j, x[j]) lies strictly above all intermediate data points:
x[k] < x[i] + (x[j] - x[i]) * (k - i) / (j - i) for all i < k < j
NVG is a superset of HVG: every HVG edge is also an NVG edge.
Complexity: O(n log n) average (sweep-line algorithm).
- Parameters:
weighted (bool or str, default False) – See HVG for weight mode options.
limit (int, optional) – Horizon limit — maximum temporal distance between connected nodes. Recommended for series > 10 000 points (2 000–5 000 suggested).
output ({"edges", "degrees", "stats"}, default "edges") – Controls what is stored after build().
only_degrees (bool)
max_edges (int | None)
max_edges_per_node (int | None)
max_memory_mb (float | None)
weight_mode (str | None)
References
Lacasa, L., Luque, B., Ballesteros, F., Luque, J., & Nuño, J. C. (2008). From time series to complex networks: The visibility graph. PNAS, 105(13), 4972–4975. https://doi.org/10.1073/pnas.0709247105
Examples
>>> import numpy as np >>> from ts2net import NVG >>> x = np.random.randn(500) >>> nvg = NVG(limit=500).build(x) >>> print(nvg.n_nodes, nvg.n_edges)
- adjacency_matrix(format='sparse')[source]
Adjacency matrix.
- Parameters:
format ({"sparse", "coo", "dense"}, default "sparse") –
"sparse"returns a SciPy CSR matrix."coo"returns a SciPy COO matrix."dense"returns a NumPy array; refused for n > 50 000 nodes (would require ≥ 20 GB RAM).- Returns:
A – Symmetric adjacency matrix of shape (n_nodes, n_nodes).
- Return type:
csr_matrix | coo_matrix | ndarray
- as_networkx(force=False)[source]
Convert to a NetworkX graph.
- Parameters:
force (bool, default False) – If False, raises for n > 200 000 nodes to prevent accidental allocation of very large objects.
- Returns:
G
- Return type:
nx.Graph or nx.DiGraph
- build(x)[source]
Build NVG from time series.
Equivalent to
fit(x); returnsselffor method chaining.- Parameters:
x (array-like of shape (n,)) – Input time series.
- Returns:
self
- Return type:
- property edges
- edges_coo()[source]
Edge list in COO (coordinate) format.
- Returns:
rows (NDArray[int64] — source node indices)
cols (NDArray[int64] — target node indices)
weights (NDArray[float64] or None — edge weights (None if unweighted))
- Return type:
Tuple[NDArray[int64], NDArray[int64], NDArray[float64] | None]
- fit(x)
Store and validate input; does not build until transform().
- Parameters:
x (NDArray[float64])
- Return type:
SklearnBuildMixin
- fit_transform(x)
Fit and transform in one step.
- Parameters:
x (NDArray[float64])
- Return type:
Graph
- property n_edges: int
Number of edges.
- property n_nodes: int
Number of nodes (equals length of input series).
- network_metrics(include=None, sample_size=None, **kwargs)[source]
Compute advanced network metrics (clustering, path lengths, modularity).
- Parameters:
include (list, optional) – Metrics to include: [“clustering”, “path_lengths”, “modularity”] If None, includes all metrics
sample_size (int, optional) – For large graphs, sample nodes/pairs for expensive computations
**kwargs – Additional arguments passed to metric functions (e.g., method, weight, resolution, seed)
- Returns:
Dictionary with network metrics: - Clustering: avg_clustering, transitivity - Path lengths: avg_path_length, diameter, radius - Modularity: modularity, n_communities
- Return type:
dict
Examples
>>> from ts2net import HVG >>> import numpy as np >>> x = np.random.randn(100) >>> hvg = HVG() >>> hvg.build(x) >>> metrics = hvg.network_metrics() >>> print(f"Clustering: {metrics['avg_clustering']:.3f}") >>> print(f"Avg path length: {metrics['avg_path_length']:.3f}") >>> print(f"Modularity: {metrics['modularity']:.3f}")
- stats(include_triangles=False)[source]
Summary statistics (no dense matrix required).
- Parameters:
include_triangles (bool)
- Return type:
dict
- test_significance(metric='density', method='shuffle', n_surrogates=200, alpha=0.05, rng=None, **kwargs)[source]
Test significance of a network metric against null distribution.
- Parameters:
metric (str, default "density") – Metric to test. Options: “density”, “deg_mean”, “deg_std”, “avg_clustering”, “assortativity”, or any key from stats()
method (str, default "shuffle") – Surrogate generation method: “shuffle”, “phase”, “circular”, “iaaft”, “block_bootstrap”
n_surrogates (int, default 200) – Number of surrogate series to generate
alpha (float, default 0.05) – Significance level (two-tailed)
rng (np.random.Generator, optional) – Random number generator
**kwargs – Additional arguments for surrogate generation (e.g., block_size for block_bootstrap)
- Returns:
result – Significance test result
- Return type:
NetworkSignificanceResult
Examples
>>> from ts2net import NVG >>> import numpy as np >>> x = np.random.randn(100) >>> nvg = NVG() >>> nvg.build(x) >>> result = nvg.test_significance(metric="density", method="phase", n_surrogates=100) >>> print(result)
- transform()
Build the network from data stored by fit().
- Return type:
Graph
- class ts2net.api.NetworkBuilder(*args, **kwargs)[source]
Bases:
ProtocolProtocol implemented by all network graph builders.
- property n_edges: int
- property n_nodes: int
- class ts2net.api.RecurrenceNetwork(m=None, tau=1, rule='knn', k=5, epsilon=0.1, metric='euclidean', only_degrees=False, output='edges')[source]
Bases:
SklearnBuildMixinRecurrence Network.
A recurrence network is derived from a recurrence plot. After delay-embedding the series into an m-dimensional phase space, two states i, j are connected if their distance falls below a threshold (
rule="epsilon") or if one is among the other’s k nearest neighbours (rule="knn").- Parameters:
m (int, optional) – Embedding dimension.
Nonemeans no embedding (1-D, i.e., the raw series is used as the phase-space trajectory).tau (int, default 1) – Time delay for Takens embedding.
rule ({"knn", "epsilon"}, default "knn") –
"knn"connects each point to its k nearest neighbours."epsilon"connects all pairs closer than epsilon.k (int, default 5) – Number of nearest neighbours (
rule="knn"only).epsilon (float, default 0.1) – Recurrence threshold (
rule="epsilon"only).metric (str, default "euclidean") – Distance metric for phase-space proximity.
output ({"edges", "degrees", "stats"}, default "edges") – Controls what is stored after build().
only_degrees (bool)
References
Marwan, N., Donges, J. F., Zou, Y., Donner, R. V., & Kurths, J. (2009). Complex network approach for recurrence analysis of time series. Physics Letters A, 373(46), 4246–4254. https://doi.org/10.1016/j.physleta.2009.09.042
Examples
>>> import numpy as np >>> from ts2net import RecurrenceNetwork >>> x = np.sin(np.linspace(0, 8*np.pi, 300)) + 0.1*np.random.randn(300) >>> rn = RecurrenceNetwork(rule="epsilon", epsilon=0.3).build(x) >>> print(rn.n_nodes, rn.n_edges)
- adjacency_matrix(format='sparse')[source]
Adjacency matrix.
- Parameters:
format ({"sparse", "coo", "dense"}, default "sparse") –
"sparse"returns a SciPy CSR matrix."coo"returns a SciPy COO matrix."dense"returns a NumPy array; refused for n > 50 000 nodes (would require ≥ 20 GB RAM).- Returns:
A – Symmetric adjacency matrix of shape (n_nodes, n_nodes).
- Return type:
csr_matrix | coo_matrix | ndarray
- as_networkx(force=False)[source]
Convert to a NetworkX graph.
- Parameters:
force (bool, default False) – If False, raises for n > 200 000 nodes to prevent accidental allocation of very large objects.
- Returns:
G
- Return type:
nx.Graph or nx.DiGraph
- build(x)[source]
Build recurrence network from time series.
- Parameters:
x (array-like of shape (n,)) – Input time series.
- Returns:
self
- Return type:
- property edges
- edges_coo()[source]
Edge list in COO (coordinate) format.
- Returns:
rows (NDArray[int64] — source node indices)
cols (NDArray[int64] — target node indices)
weights (NDArray[float64] or None — edge weights (None if unweighted))
- Return type:
Tuple[NDArray[int64], NDArray[int64], NDArray[float64] | None]
- fit(x)
Store and validate input; does not build until transform().
- Parameters:
x (NDArray[float64])
- Return type:
SklearnBuildMixin
- fit_transform(x)
Fit and transform in one step.
- Parameters:
x (NDArray[float64])
- Return type:
Graph
- property n_edges: int
Number of edges.
- property n_nodes: int
Number of nodes (equals length of input series).
- stats(include_triangles=False)[source]
Summary statistics (no dense matrix required).
- Parameters:
include_triangles (bool)
- Return type:
dict
- transform()
Build the network from data stored by fit().
- Return type:
Graph
- class ts2net.api.TransitionNetwork(symbolizer='ordinal', order=3, delay=1, tie_rule='stable', bins=5, normalize=True, sparse=False, only_degrees=False, output='edges')[source]
Bases:
SklearnBuildMixinTransition Network (Ordinal Partition Network).
The time series is symbolised — each subsequence of length
order+1is mapped to its rank-order pattern (an ordinal pattern). A directed graph is then built where nodes are distinct patterns and a weighted edge (i → j) records how often pattern i is immediately followed by pattern j.The resulting graph captures the Markov-like transition dynamics of the series and is sensitive to nonlinear structure invisible to linear methods.
- Parameters:
symbolizer ({"ordinal", "equal_width", "equal_freq", "kmeans"}) – How to discretise the series into symbolic states.
"ordinal"(default) uses rank-order patterns — invariant to monotone transformations and well-studied analytically.order (int, default 3) – Pattern length =
order + 1.order=3gives 3! = 6 possible patterns. Larger values capture longer-range dependencies at the cost of sparsity (and needing longer series).delay (int, default 1) – Sampling delay for pattern extraction.
output ({"edges", "degrees", "stats"}, default "edges") – Controls what is stored after build().
tie_rule (str)
bins (int)
normalize (bool)
sparse (bool)
only_degrees (bool)
References
Small, M. (2013). Complex networks from time series: Capturing nonlinear dynamics. Chaos, 23(3), 033127. https://doi.org/10.1063/1.4818261
Examples
>>> import numpy as np >>> from ts2net import TransitionNetwork >>> x = np.random.randn(500) >>> tn = TransitionNetwork(order=3).build(x) >>> print(tn.n_nodes, tn.n_edges) # nodes = distinct patterns, directed
- adjacency_matrix(format='sparse')[source]
Adjacency matrix.
- Parameters:
format ({"sparse", "coo", "dense"}, default "sparse") –
"sparse"returns a SciPy CSR matrix."coo"returns a SciPy COO matrix."dense"returns a NumPy array; refused for n > 50 000 nodes (would require ≥ 20 GB RAM).- Returns:
A – Symmetric adjacency matrix of shape (n_nodes, n_nodes).
- Return type:
csr_matrix | coo_matrix | ndarray
- as_networkx(force=False)[source]
Convert to a NetworkX graph.
- Parameters:
force (bool, default False) – If False, raises for n > 200 000 nodes to prevent accidental allocation of very large objects.
- Returns:
G
- Return type:
nx.Graph or nx.DiGraph
- build(x)[source]
Build transition network from time series.
- Parameters:
x (array-like of shape (n,)) – Input time series.
- Returns:
self
- Return type:
- property edges
- edges_coo()[source]
Edge list in COO (coordinate) format.
- Returns:
rows (NDArray[int64] — source node indices)
cols (NDArray[int64] — target node indices)
weights (NDArray[float64] or None — edge weights (None if unweighted))
- Return type:
Tuple[NDArray[int64], NDArray[int64], NDArray[float64] | None]
- fit(x)
Store and validate input; does not build until transform().
- Parameters:
x (NDArray[float64])
- Return type:
SklearnBuildMixin
- fit_transform(x)
Fit and transform in one step.
- Parameters:
x (NDArray[float64])
- Return type:
Graph
- property n_edges: int
Number of edges.
- property n_nodes: int
Number of nodes (equals length of input series).
- stats(include_triangles=False)[source]
Summary statistics (no dense matrix required).
- Parameters:
include_triangles (bool)
- Return type:
dict
- transform()
Build the network from data stored by fit().
- Return type:
Graph
- ts2net.api.build_network(x, method, **kwargs)[source]
Build network from time series (factory pattern).
- Parameters:
x (array) – Time series
method (str) – ‘hvg’, ‘nvg’, ‘recurrence’, ‘transition’
**kwargs – Method-specific parameters
- Returns:
graph – Built network with .edges, .degree_sequence(), etc.
- Return type:
Graph-like object
Examples
>>> x = np.random.randn(1000) >>> hvg = build_network(x, 'hvg') >>> rn = build_network(x, 'recurrence', m=3, rule='knn', k=5)
Core
Core module for time series to network conversion.
This module provides implementations of various time series to network conversion algorithms including Recurrence Networks, Visibility Graphs, and Transition Networks.
- ts2net.core.batch_transform(X, builder, **kwargs)[source]
Transform multiple time series using the specified builder.
- Parameters:
X (Sequence[np.ndarray]) – Sequence of time series arrays
builder (str) – Name of the builder to use
**kwargs – Additional keyword arguments for the builder
- Returns:
List of transformed graphs
- Return type:
List[Union[nx.Graph, nx.DiGraph]]
- ts2net.core.directed_3node_motifs(G, max_samples=None, seed=3363)[source]
- Parameters:
G (DiGraph)
max_samples (int | None)
seed (int)
- Return type:
dict
- ts2net.core.embed(x, m, tau)[source]
Time-delay embedding of a time series.
- Parameters:
x (np.ndarray) – 1D time series
m (int) – Embedding dimension
tau (int) – Time delay
- Returns:
2D array of shape (L, m) where L = len(x) - (m-1)*tau
- Return type:
np.ndarray
- ts2net.core.graph_summary(G, motifs=None, motif_samples=None, seed=3363)[source]
Compute a comprehensive summary of graph properties.
- Parameters:
G (nx.Graph or nx.DiGraph) – Input graph
motifs (str, optional) – Type of motifs to compute (‘3node’, ‘4node’, or None)
motif_samples (int, optional) – Maximum number of samples for motif counting
seed (int, default 3363) – Random seed for sampling
- Returns:
Dictionary of graph properties
- Return type:
dict
- ts2net.core.motif_counts(G, motif_type='3node', max_samples=None, seed=3363)[source]
Count motifs in a graph.
- Parameters:
G (nx.Graph or nx.DiGraph) – Input graph
motif_type (str, default '3node') – Type of motifs to count (‘3node’ or ‘4node’)
max_samples (int, optional) – Maximum number of samples for motif counting
seed (int, default 3363) – Random seed for sampling
- Returns:
Dictionary of motif counts
- Return type:
Dict[str, int]
Visualization
Visualization module for ts2net.
Clean, scalable plotting functions for time series network analysis. All functions return (fig, ax) for further customization.
- class ts2net.viz.TSGraph(graph, pos, meta)[source]
Bases:
objectContainer for a time-series-derived graph plus geometry and build metadata.
- Parameters:
graph (Graph | DiGraph)
pos (Dict[int, ndarray] | None)
meta (Dict[str, Any])
- graph
NetworkX graph with node and edge attributes.
- Type:
networkx.classes.graph.Graph | networkx.classes.digraph.DiGraph
- pos
Optional 2D coordinates for nodes. Keys match graph nodes. Defaults to (t, x[t]) for visibility graphs.
- Type:
Dict[int, numpy.ndarray] | None
- meta
Build metadata such as method, parameters, and data shape.
- Type:
Dict[str, Any]
- graph: Graph | DiGraph
- meta: Dict[str, Any]
- pos: Dict[int, ndarray] | None
- ts2net.viz.build_ordinal_partition_graph(x, *, embed_dim=4, delay=1, directed=True, weighted=True, include_self_loops=True, tie_break='stable', return_pos=False, dtype=<class 'numpy.float64'>)[source]
Build an ordinal partition network.
Nodes represent permutation patterns. Directed edges represent observed transitions between patterns. Edge weight equals count or probability.
- Parameters:
x (ndarray | Iterable[float]) – 1D time series.
embed_dim (int) – Embedding dimension d (order of permutation).
delay (int) – Time delay τ.
directed (bool) – If True, create directed graph (default True).
weighted (bool) – If True, edge weights are transition counts.
include_self_loops (bool) – If True, allow self-transitions.
tie_break (Literal['stable', 'jitter']) – How to handle ties in permutation patterns. - “stable”: Use stable sort (preserves order of ties). - “jitter”: Add small noise to break ties.
return_pos (bool) – If True, compute 2D positions for nodes (default False).
dtype (dtype) – Numeric dtype.
- Returns:
graph: DiGraph (or Graph if directed=False) with pattern nodes.
node attribute “pattern”: tuple[int, …] representing permutation.
node attribute “count”: occurrence count of pattern.
edge attribute “weight”: transition count (if weighted).
pos: Optional 2D positions for visualization.
meta: Build parameters and statistics.
- Return type:
TSGraph with
- ts2net.viz.build_recurrence_graph(x, *, embed_dim=3, delay=1, eps=0.2, eps_mode='fraction_max', metric='euclidean', exclude_diagonal=True, theiler_window=0, knn=0, knn_mode='none', weighted=False, weight_mode='inverse_distance', return_pos=True, node_id='time', dtype=<class 'numpy.float64'>)[source]
Build an ε-recurrence network from a time series.
You embed the series into state space, then connect nodes whose state vectors fall within an ε ball. This matches the style in recurrence-network figures where ε changes density.
- Parameters:
x (ndarray | Iterable[float]) – 1D array-like of shape (n,) or array of shape (n, p) for multivariate.
embed_dim (int) – Embedding dimension m.
delay (int) – Delay τ in samples.
eps (float) – Threshold value. Interpreted by eps_mode.
eps_mode (Literal['fraction_max', 'percentile']) – How to interpret eps. - “fraction_max”: eps * max_pairwise_distance. - “percentile”: eps is a percentile in [0, 100].
metric (Literal['euclidean', 'sqeuclidean', 'manhattan', 'chebyshev']) – Distance metric in state space.
exclude_diagonal (bool) – Remove self edges.
theiler_window (int) – Exclude edges for |i - j| <= theiler_window.
knn (int) – If > 0, also connect k nearest neighbors per node.
knn_mode (Literal['none', 'mutual', 'directed']) – How to apply knn edges. - “none”: ignore knn parameter. - “mutual”: keep only mutual kNN edges. - “directed”: create directed kNN edges (returns DiGraph).
weighted (bool) – Store weights on edges.
weight_mode (Literal['distance', 'inverse_distance']) – Weight definition if weighted.
return_pos (bool) – If True, return node positions as embedded vectors.
node_id (Literal['time', 'state']) – Node labeling scheme. - “time”: node id equals time index i. - “state”: node id equals integer state index in embedding.
dtype (dtype) – Numeric dtype.
- Returns:
graph nodes ordered by time index.
node attributes: “t” time index, “state” embedded vector.
edge attributes: “dist” and optionally “weight”.
pos: embedded vectors (or None).
meta: method and parameters.
- Return type:
TSGraph with
- ts2net.viz.build_visibility_graph(x, *, kind='hvg', directed=False, weighted=False, weight_mode=None, limit=None, max_edges=None, max_edges_per_node=None, max_memory_mb=None, include_self_loops=False, return_pos=True, dtype=<class 'numpy.float64'>)[source]
Construct HVG or NVG style graphs with optional direction and weights.
Nodes map to time index i. Edge direction uses time forward orientation i -> j when i < j. Weights attach as edge attribute “weight”. Distances and aux values attach as edge attributes when needed.
- Parameters:
x (ndarray | Iterable[float]) – 1D series.
kind (Literal['hvg', 'nvg', 'bounded_nvg']) – hvg, nvg, or bounded_nvg.
directed (bool) – If True, emit a DiGraph and only time forward edges.
weighted (bool | Literal['none', 'absdiff', 'time_gap', 'min_clearance', 'slope']) – False, True, or a string mode.
weight_mode (Literal['none', 'absdiff', 'time_gap', 'min_clearance', 'slope'] | None) – Optional explicit mode. Overrides weighted when set.
limit (int | None) – Window limit for NVG variants.
max_edges (int | None) – Global cap for bounded_nvg.
max_edges_per_node (int | None) – Per node cap for bounded_nvg.
max_memory_mb (int | None) – Memory guard for bounded_nvg.
include_self_loops (bool) – Rare. Default False.
return_pos (bool) – If True, pos uses (t, x[t]) so plots match the series.
dtype (dtype) – Numeric dtype.
- Returns:
TSGraph container with graph, pos, and meta.
- Return type:
- ts2net.viz.draw_tsgraph(tsgraph, *, ax=None, node_size=10.0, edge_alpha=0.15, node_alpha=0.9, color_by='time', cmap='viridis', show=True, layout=None)[source]
Draw graph with thin edges and colored nodes.
Expects tsgraph.pos. Falls back to a layout if pos is None.
- Parameters:
tsgraph (TSGraph) – Graph container with graph, pos, and meta
ax (matplotlib.axes.Axes, optional) – Axes to draw on (creates new figure if None)
node_size (float, default 10.0) – Size of nodes in points
edge_alpha (float, default 0.15) – Transparency of edges (0-1)
node_alpha (float, default 0.9) – Transparency of nodes (0-1)
color_by (str, default "time") – Node coloring scheme: - “time”: Color by time index (uses node attribute ‘t’) - “degree”: Color by node degree - “community”: Color by community (requires community detection) - “none”: Single color for all nodes
cmap (str, default "viridis") – Colormap name for node colors
show (bool, default True) – If True, call plt.show()
layout (str, optional) – Layout algorithm if pos is None (e.g., “spring”, “kamada_kawai”) Defaults to “spring” for undirected, “circular” for directed
- Returns:
fig (matplotlib.figure.Figure)
ax (matplotlib.axes.Axes)
- Return type:
Tuple[Figure, Axes]
- ts2net.viz.optimal_dim(x, delay=1, dim_range=(2, 8))[source]
Estimate optimal embedding dimension d by maximizing OPN degree variance.
This heuristic builds ordinal partition networks for different dimensions and selects the dimension that maximizes variance in the degree distribution. Higher variance suggests richer structure.
- Parameters:
x (ndarray) – 1D time series.
delay (int) – Time delay τ (use optimal_lag if unsure).
dim_range (Tuple[int, int]) – (min_dim, max_dim) to search.
- Returns:
Optimal embedding dimension d.
- Return type:
int
- ts2net.viz.optimal_lag(x, max_lag=50)[source]
Estimate optimal time delay τ using first zero of autocorrelation.
This is a simple heuristic: find the first lag where autocorrelation crosses zero. If no zero crossing, return lag with minimum autocorrelation.
- Parameters:
x (ndarray) – 1D time series.
max_lag (int) – Maximum lag to consider.
- Returns:
Optimal delay τ (in samples).
- Return type:
int
- ts2net.viz.plot_degree_ccdf(degrees, title=None, figsize=None)[source]
Figure 3: Degree distribution as CCDF (Complementary CDF).
Plots the complementary CDF of degrees on log y scale. Works better than a histogram, stays stable across sample size, makes cross-zone comparison easy.
- Parameters:
degrees (array (n,)) – Degree sequence
title (str, optional) – Plot title
figsize (tuple, optional) – Figure size (default: (10, 6))
- Returns:
fig (matplotlib.figure.Figure)
ax (matplotlib.axes.Axes)
- Return type:
Tuple[Figure, Axes]
- ts2net.viz.plot_degree_profile(degrees, time_index=None, title=None, figsize=None)[source]
Figure 2: Degree profile across time.
Plots degree versus time index. This becomes a direct proxy for “local complexity” in the signal. Reads well and scales well.
- Parameters:
degrees (array (n,)) – Degree sequence (one per node/time point)
time_index (array (n,), optional) – Time indices (default: 0, 1, 2, …)
title (str, optional) – Plot title
figsize (tuple, optional) – Figure size (default: (10, 6))
- Returns:
fig (matplotlib.figure.Figure)
ax (matplotlib.axes.Axes)
- Return type:
Tuple[Figure, Axes]
- ts2net.viz.plot_hvg_small(x, edges, time_index=None, title=None, figsize=None)[source]
Optional: Small n graph drawing for HVG.
Uses fixed layout based on time index. Nodes at x = time, y = normalized value. Edges drawn as faint arcs or straight lines. Shows visibility logic.
- Parameters:
x (array (n,)) – Time series values
edges (list of tuples) – Edge list [(i, j), …]
time_index (array (n,), optional) – Time indices (default: 0, 1, 2, …)
title (str, optional) – Plot title
figsize (tuple, optional) – Figure size (default: (10, 6))
- Returns:
fig (matplotlib.figure.Figure)
ax (matplotlib.axes.Axes)
- Return type:
Tuple[Figure, Axes]
- ts2net.viz.plot_method_comparison(df_metrics, methods=None, figsize=None)[source]
Figure 4: Method comparison panel.
Creates a small table graphic with three aligned dot plots: - Edge count - Average degree - Normalized density (edges / n)
Uses one axis per metric. Zones/methods on y-axis.
- Parameters:
df_metrics (dict or array) – Dictionary mapping method names to dicts with ‘n_edges’, ‘avg_degree’, ‘density’ OR array of dicts with ‘method’ key
methods (list of str, optional) – Method names (if df_metrics is array)
figsize (tuple, optional) – Figure size (default: (12, 6))
- Returns:
fig (matplotlib.figure.Figure)
axes (list of matplotlib.axes.Axes)
- Return type:
Tuple[Figure, List[Axes]]
- ts2net.viz.plot_recurrence_matrix(recurrence_matrix, title=None, figsize=None)[source]
Optional: Recurrence plot style view for recurrence networks.
Draws the recurrence matrix as an image for a short window. Users already understand this visual.
- Parameters:
recurrence_matrix (array (n, n)) – Recurrence/adjacency matrix
title (str, optional) – Plot title
figsize (tuple, optional) – Figure size (default: (8, 8))
- Returns:
fig (matplotlib.figure.Figure)
ax (matplotlib.axes.Axes)
- Return type:
Tuple[Figure, Axes]
- ts2net.viz.plot_series_with_events(x, events=None, window=None, window_bounds=None, time_index=None, title=None, figsize=None)[source]
Figure 1: Time series with change points and window boundaries.
Shows the signal with detected change points as thin vertical lines and window edges as faint bands. Provides context for network results.
- Parameters:
x (array (n,)) – Time series values
events (array (m,), optional) – Indices of detected change points
window (tuple (start, end), optional) – Single window boundaries to highlight
window_bounds (list of tuples, optional) – Multiple window boundaries [(start, end), …]
time_index (array (n,), optional) – Time indices (default: 0, 1, 2, …)
title (str, optional) – Plot title
figsize (tuple, optional) – Figure size (default: (10, 6))
- Returns:
fig (matplotlib.figure.Figure)
ax (matplotlib.axes.Axes)
- Return type:
Tuple[Figure, Axes]
- ts2net.viz.plot_timeseries_network(graphs, timestamps, pos=None, node_colors=None, title='Time Series Network Evolution', show=True, filename=None)[source]
Create an interactive Plotly visualization showing network evolution over time.
- Parameters:
graphs (list of nx.Graph) – List of NetworkX graphs, one for each time step
timestamps (list) – List of timestamps/labels for each time step (e.g., dates, indices)
pos (dict, optional) – Node positions dictionary. If None, computes spring layout from first graph
node_colors (str, list, or dict, optional) – Node coloring scheme: - “degree”: Color by node degree - “time”: Color by time index - list: List of colors for each node - dict: Mapping of node -> color
title (str, default "Time Series Network Evolution") – Plot title
show (bool, default True) – If True, display the plot
filename (str, optional) – If provided, save the plot to this HTML file
- Returns:
fig – Interactive Plotly figure with time slider
- Return type:
plotly.graph_objects.Figure
Examples
>>> from ts2net.viz.plotly_viz import plot_timeseries_network >>> import networkx as nx >>> >>> # Create example graphs for different time steps >>> graphs = [nx.erdos_renyi_graph(20, 0.3) for _ in range(5)] >>> timestamps = [f"Step {i}" for i in range(5)] >>> >>> fig = plot_timeseries_network(graphs, timestamps) >>> fig.show()
- ts2net.viz.plot_window_feature_map(df_window_features, feature_names=None, time_labels=None, figsize=None)[source]
Figure 5: Window level feature map.
Computes window stats (mean degree, degree variance, assortativity proxy, transition entropy) and plots as a heatmap with time on x and feature on y. Provides anomaly signatures.
- Parameters:
df_window_features (dict or array) – Dictionary mapping feature names to arrays OR array of dicts
feature_names (list of str, optional) – Feature names (if df_window_features is dict, uses keys)
time_labels (list of str, optional) – Time window labels (default: 0, 1, 2, …)
figsize (tuple, optional) – Figure size (default: (12, 8))
- Returns:
fig (matplotlib.figure.Figure)
ax (matplotlib.axes.Axes)
- Return type:
Tuple[Figure, Axes]
- ts2net.viz.plot_windowed_networks(x, window, step=1, method='hvg', pos=None, **method_kwargs)[source]
Create interactive visualization of networks built from sliding windows.
- Parameters:
x (array (n_points,)) – Input time series
window (int) – Window width (number of time points per window)
step (int, default 1) – Step size between consecutive windows
method (str, default "hvg") – Network method: ‘hvg’, ‘nvg’, ‘recurrence’, ‘transition’
pos (dict, optional) – Node positions. If None, computes from first window
**method_kwargs – Additional parameters for the network builder
- Returns:
fig – Interactive Plotly figure
- Return type:
plotly.graph_objects.Figure
Examples
>>> import numpy as np >>> from ts2net.viz.plotly_viz import plot_windowed_networks >>> >>> x = np.random.randn(1000) >>> fig = plot_windowed_networks(x, window=50, step=10, method='hvg') >>> fig.show()
Unified Graph API
Unified graph visualization API for ts2net.
Provides TSGraph dataclass and builder functions for creating visualization-ready graph objects with geometry and metadata.
- class ts2net.viz.graph.TSGraph(graph, pos, meta)[source]
Bases:
objectContainer for a time-series-derived graph plus geometry and build metadata.
- Parameters:
graph (Graph | DiGraph)
pos (Dict[int, ndarray] | None)
meta (Dict[str, Any])
- graph
NetworkX graph with node and edge attributes.
- Type:
networkx.classes.graph.Graph | networkx.classes.digraph.DiGraph
- pos
Optional 2D coordinates for nodes. Keys match graph nodes. Defaults to (t, x[t]) for visibility graphs.
- Type:
Dict[int, numpy.ndarray] | None
- meta
Build metadata such as method, parameters, and data shape.
- Type:
Dict[str, Any]
- graph: Graph | DiGraph
- meta: Dict[str, Any]
- pos: Dict[int, ndarray] | None
- ts2net.viz.graph.build_ordinal_partition_graph(x, *, embed_dim=4, delay=1, directed=True, weighted=True, include_self_loops=True, tie_break='stable', return_pos=False, dtype=<class 'numpy.float64'>)[source]
Build an ordinal partition network.
Nodes represent permutation patterns. Directed edges represent observed transitions between patterns. Edge weight equals count or probability.
- Parameters:
x (ndarray | Iterable[float]) – 1D time series.
embed_dim (int) – Embedding dimension d (order of permutation).
delay (int) – Time delay τ.
directed (bool) – If True, create directed graph (default True).
weighted (bool) – If True, edge weights are transition counts.
include_self_loops (bool) – If True, allow self-transitions.
tie_break (Literal['stable', 'jitter']) – How to handle ties in permutation patterns. - “stable”: Use stable sort (preserves order of ties). - “jitter”: Add small noise to break ties.
return_pos (bool) – If True, compute 2D positions for nodes (default False).
dtype (dtype) – Numeric dtype.
- Returns:
graph: DiGraph (or Graph if directed=False) with pattern nodes.
node attribute “pattern”: tuple[int, …] representing permutation.
node attribute “count”: occurrence count of pattern.
edge attribute “weight”: transition count (if weighted).
pos: Optional 2D positions for visualization.
meta: Build parameters and statistics.
- Return type:
TSGraph with
- ts2net.viz.graph.build_recurrence_graph(x, *, embed_dim=3, delay=1, eps=0.2, eps_mode='fraction_max', metric='euclidean', exclude_diagonal=True, theiler_window=0, knn=0, knn_mode='none', weighted=False, weight_mode='inverse_distance', return_pos=True, node_id='time', dtype=<class 'numpy.float64'>)[source]
Build an ε-recurrence network from a time series.
You embed the series into state space, then connect nodes whose state vectors fall within an ε ball. This matches the style in recurrence-network figures where ε changes density.
- Parameters:
x (ndarray | Iterable[float]) – 1D array-like of shape (n,) or array of shape (n, p) for multivariate.
embed_dim (int) – Embedding dimension m.
delay (int) – Delay τ in samples.
eps (float) – Threshold value. Interpreted by eps_mode.
eps_mode (Literal['fraction_max', 'percentile']) – How to interpret eps. - “fraction_max”: eps * max_pairwise_distance. - “percentile”: eps is a percentile in [0, 100].
metric (Literal['euclidean', 'sqeuclidean', 'manhattan', 'chebyshev']) – Distance metric in state space.
exclude_diagonal (bool) – Remove self edges.
theiler_window (int) – Exclude edges for |i - j| <= theiler_window.
knn (int) – If > 0, also connect k nearest neighbors per node.
knn_mode (Literal['none', 'mutual', 'directed']) – How to apply knn edges. - “none”: ignore knn parameter. - “mutual”: keep only mutual kNN edges. - “directed”: create directed kNN edges (returns DiGraph).
weighted (bool) – Store weights on edges.
weight_mode (Literal['distance', 'inverse_distance']) – Weight definition if weighted.
return_pos (bool) – If True, return node positions as embedded vectors.
node_id (Literal['time', 'state']) – Node labeling scheme. - “time”: node id equals time index i. - “state”: node id equals integer state index in embedding.
dtype (dtype) – Numeric dtype.
- Returns:
graph nodes ordered by time index.
node attributes: “t” time index, “state” embedded vector.
edge attributes: “dist” and optionally “weight”.
pos: embedded vectors (or None).
meta: method and parameters.
- Return type:
TSGraph with
- ts2net.viz.graph.build_visibility_graph(x, *, kind='hvg', directed=False, weighted=False, weight_mode=None, limit=None, max_edges=None, max_edges_per_node=None, max_memory_mb=None, include_self_loops=False, return_pos=True, dtype=<class 'numpy.float64'>)[source]
Construct HVG or NVG style graphs with optional direction and weights.
Nodes map to time index i. Edge direction uses time forward orientation i -> j when i < j. Weights attach as edge attribute “weight”. Distances and aux values attach as edge attributes when needed.
- Parameters:
x (ndarray | Iterable[float]) – 1D series.
kind (Literal['hvg', 'nvg', 'bounded_nvg']) – hvg, nvg, or bounded_nvg.
directed (bool) – If True, emit a DiGraph and only time forward edges.
weighted (bool | Literal['none', 'absdiff', 'time_gap', 'min_clearance', 'slope']) – False, True, or a string mode.
weight_mode (Literal['none', 'absdiff', 'time_gap', 'min_clearance', 'slope'] | None) – Optional explicit mode. Overrides weighted when set.
limit (int | None) – Window limit for NVG variants.
max_edges (int | None) – Global cap for bounded_nvg.
max_edges_per_node (int | None) – Per node cap for bounded_nvg.
max_memory_mb (int | None) – Memory guard for bounded_nvg.
include_self_loops (bool) – Rare. Default False.
return_pos (bool) – If True, pos uses (t, x[t]) so plots match the series.
dtype (dtype) – Numeric dtype.
- Returns:
TSGraph container with graph, pos, and meta.
- Return type:
- ts2net.viz.graph.optimal_dim(x, delay=1, dim_range=(2, 8))[source]
Estimate optimal embedding dimension d by maximizing OPN degree variance.
This heuristic builds ordinal partition networks for different dimensions and selects the dimension that maximizes variance in the degree distribution. Higher variance suggests richer structure.
- Parameters:
x (ndarray) – 1D time series.
delay (int) – Time delay τ (use optimal_lag if unsure).
dim_range (Tuple[int, int]) – (min_dim, max_dim) to search.
- Returns:
Optimal embedding dimension d.
- Return type:
int
- ts2net.viz.graph.optimal_lag(x, max_lag=50)[source]
Estimate optimal time delay τ using first zero of autocorrelation.
This is a simple heuristic: find the first lag where autocorrelation crosses zero. If no zero crossing, return lag with minimum autocorrelation.
- Parameters:
x (ndarray) – 1D time series.
max_lag (int) – Maximum lag to consider.
- Returns:
Optimal delay τ (in samples).
- Return type:
int
Multivariate
Multivariate time series to network construction.
This module provides tools to construct networks from multiple time series, where nodes represent time series and edges represent similarities/associations.
Examples
>>> import numpy as np
>>> from ts2net.multivariate import ts_dist, net_knn
>>> X = np.random.randn(10, 100) # 10 time series, 100 points each
>>> D = ts_dist(X, method='correlation', n_jobs=-1)
>>> G, A = net_knn(D, k=3)
>>> print(f"Network: {G.number_of_nodes()} nodes, {G.number_of_edges()} edges")
- ts2net.multivariate.cluster_series_by_features(features_df, n_clusters=None, method='kmeans')[source]
Cluster time series based on their network features.
Groups series with similar network properties together.
- Parameters:
features_df (pandas.DataFrame) – DataFrame from compute_network_features() with network features
n_clusters (int, optional) – Number of clusters (if None, uses elbow method)
method (str, default "kmeans") – Clustering method: “kmeans” or “hierarchical”
- Returns:
clusters – Dictionary mapping series name to cluster ID
- Return type:
dict
Examples
>>> features = compute_network_features(X, method="hvg") >>> clusters = cluster_series_by_features(features, n_clusters=3) >>> print(f"Series grouped into {len(set(clusters.values()))} clusters")
- ts2net.multivariate.compare_network_features(features_df, metric=None)[source]
Compare network features across multiple series.
Computes summary statistics and similarity measures for network features across different time series.
- Parameters:
features_df (pandas.DataFrame) – DataFrame from compute_network_features() with network features for multiple series
metric (str, optional) – Specific metric to compare (if None, compares all numeric columns)
- Returns:
comparison – Dictionary with comparison metrics: - “mean”: Mean value across series - “std”: Standard deviation across series - “min”: Minimum value - “max”: Maximum value - “range”: Range (max - min) - “cv”: Coefficient of variation (std / mean) - “similarity_matrix”: Correlation matrix of features (if multiple metrics)
- Return type:
dict
Examples
>>> features = compute_network_features(X, method="hvg") >>> comparison = compare_network_features(features) >>> print(f"Avg density: {comparison['density']['mean']:.3f}") >>> print(f"Density CV: {comparison['density']['cv']:.3f}")
- ts2net.multivariate.compute_network_features(X, method='hvg', series_names=None, **kwargs)[source]
Compute network features for multiple time series.
For each time series, builds a network and extracts summary statistics. Returns a DataFrame with one row per series and columns for each feature.
- Parameters:
X (list of arrays or array (n_series, n_points)) – Multiple time series to analyze
method (str, default "hvg") – Network construction method: “hvg”, “nvg”, “recurrence”, or “transition”
series_names (list of str, optional) – Names for each series (default: “Series_0”, “Series_1”, …)
**kwargs – Additional arguments passed to network builder (e.g., weighted, k, threshold)
- Returns:
df – DataFrame with network features for each series: - n_nodes: Number of nodes - n_edges: Number of edges - density: Edge density - avg_degree: Average degree - std_degree: Standard deviation of degree - min_degree: Minimum degree - max_degree: Maximum degree - (and method-specific features)
- Return type:
pandas.DataFrame
Examples
>>> import numpy as np >>> from ts2net.multivariate import compute_network_features >>> >>> # Create multiple time series >>> X = [np.random.randn(100) for _ in range(5)] >>> >>> # Compute HVG features for all series >>> features = compute_network_features(X, method="hvg") >>> print(features) >>> >>> # Compare series >>> print(features.describe())
- ts2net.multivariate.coupling_strength(x1, x2, method='joint_recurrence', threshold=None, k=None)[source]
Compute coupling strength between two time series.
- Parameters:
x1 (array (n,)) – First time series
x2 (array (n,)) – Second time series
method (str, default "joint_recurrence") – Coupling method: “joint_recurrence” or “cross_visibility”
threshold (float, optional) – Threshold for recurrence (if method=”joint_recurrence”)
k (int, optional) – k for k-NN recurrence (if method=”joint_recurrence”)
- Returns:
metrics – Dictionary with coupling metrics: - coupling_strength: Overall coupling strength (0-1) - joint_recurrence_rate: Fraction of joint recurrences - synchronization: Degree of synchronization - asymmetry: Asymmetry in coupling (0 = symmetric)
- Return type:
dict
Examples
>>> import numpy as np >>> x1 = np.random.randn(100) >>> x2 = x1 + 0.1 * np.random.randn(100) # Coupled series >>> metrics = coupling_strength(x1, x2, method="joint_recurrence", threshold=0.5) >>> print(f"Coupling strength: {metrics['coupling_strength']:.3f}")
- ts2net.multivariate.cross_visibility_graph(x1, x2, method='hvg', weighted=False, weight_mode=None, limit=None, directed=False)[source]
Construct a cross visibility graph between two time series.
A cross visibility graph connects points from different series if they are visible to each other. Visibility is determined by the visibility criterion applied across series boundaries.
- Parameters:
x1 (array (n1,)) – First time series
x2 (array (n2,)) – Second time series (can have different length)
method (str, default "hvg") – Visibility method: “hvg” (horizontal) or “nvg” (natural)
weighted (bool or str, default False) – If True, use “absdiff” weight mode. If str, use that weight mode.
weight_mode (str, optional) – Explicit weight mode (overrides weighted if provided)
limit (int, optional) – Maximum temporal distance for visibility
directed (bool, default False) – If True, create directed graph
- Returns:
G (networkx.Graph or DiGraph) – Cross visibility graph (bipartite: nodes 0..n1-1 from x1, n1..n1+n2-1 from x2)
A (array (n1+n2, n1+n2)) – Adjacency matrix
- Return type:
Tuple[Graph, NDArray]
Examples
>>> import numpy as np >>> x1 = np.random.randn(50) >>> x2 = np.random.randn(50) >>> G, A = cross_visibility_graph(x1, x2, method="hvg") >>> print(f"Cross visibility: {G.number_of_nodes()} nodes, {G.number_of_edges()} edges")
- ts2net.multivariate.joint_recurrence_network(x1, x2, threshold=None, k=None, method='epsilon', metric='euclidean', weighted=False, directed=False)[source]
Construct a joint recurrence network from two time series.
A joint recurrence occurs when both series are recurrent at the same time. An edge (i, j) exists if: - Series 1: points i and j are recurrent (within threshold or k-NN) - Series 2: points i and j are recurrent (within threshold or k-NN)
- Parameters:
x1 (array (n,)) – First time series
x2 (array (n,)) – Second time series (must have same length as x1)
threshold (float, optional) – Distance threshold for epsilon recurrence (required if method=”epsilon”)
k (int, optional) – Number of nearest neighbors for k-NN recurrence (required if method=”knn”)
method (str, default "epsilon") – Recurrence method: “epsilon” (threshold-based) or “knn” (k-nearest neighbors)
metric (str, default "euclidean") – Distance metric (only used for embedding if needed)
weighted (bool, default False) – If True, weight edges by average distance
directed (bool, default False) – If True, create directed graph
- Returns:
G (networkx.Graph or DiGraph) – Joint recurrence network
A (array (n, n)) – Adjacency matrix
- Return type:
Tuple[Graph, NDArray]
Examples
>>> import numpy as np >>> x1 = np.random.randn(100) >>> x2 = np.random.randn(100) >>> G, A = joint_recurrence_network(x1, x2, threshold=0.5, method="epsilon") >>> print(f"Joint recurrence network: {G.number_of_nodes()} nodes, {G.number_of_edges()} edges")
- ts2net.multivariate.net_enn(D, epsilon=None, percentile=None, weighted=False, directed=False)[source]
ε-Nearest Neighbors network from distance matrix.
Nodes are connected if distance < ε.
- Parameters:
D (array (n, n)) – Distance matrix
epsilon (float, optional) – Distance threshold (connect if D[i,j] < epsilon)
percentile (float, optional) – Use percentile of distances as epsilon (0-100) If both epsilon and percentile given, epsilon takes precedence
weighted (bool) – If True, edge weights = distances
directed (bool) – If True, create directed graph
- Returns:
G (networkx.Graph or DiGraph) – ε-NN network
A (array (n, n)) – Adjacency matrix
- Return type:
Tuple[Graph, ndarray]
Examples
>>> D = np.random.rand(10, 10) >>> # Connect top 30% shortest distances >>> G, A = net_enn(D, percentile=30, weighted=False)
- ts2net.multivariate.net_enn_approx(D, epsilon=None, percentile=None, metric='precomputed', n_neighbors=50, weighted=False, directed=False)[source]
Approximate ε-NN network using PyNNDescent.
Faster than exact ε-NN for large datasets, but may miss some edges.
- Parameters:
D (array (n, n)) – Distance matrix or feature matrix
epsilon (float, optional) – Distance threshold
percentile (float, optional) – Use percentile of distances (if epsilon is None)
metric (str) – ‘precomputed’ or distance metric name
n_neighbors (int) – Number of neighbors to search (larger = more accurate)
weighted (bool) – If True, edge weights = distances
directed (bool) – If True, create directed graph
- Returns:
G (networkx.Graph or DiGraph) – Approximate ε-NN network
A (array (n, n)) – Adjacency matrix
- Return type:
Tuple[Graph, ndarray]
Notes
Requires: pip install pynndescent
- ts2net.multivariate.net_knn(D, k, mutual=False, weighted=False, directed=False)[source]
k-Nearest Neighbors network from distance matrix.
Each node is connected to its k nearest neighbors.
- Parameters:
D (array (n, n)) – Distance matrix (smaller = more similar)
k (int) – Number of nearest neighbors per node
mutual (bool) – If True, require mutual k-NN (i in kNN(j) AND j in kNN(i))
weighted (bool) – If True, edge weights = distances
directed (bool) – If True, create directed graph (i → j if j in kNN(i))
- Returns:
G (networkx.Graph or DiGraph) – k-NN network
A (array (n, n)) – Adjacency matrix (weighted if weighted=True)
- Return type:
Tuple[Graph, ndarray]
Examples
>>> D = np.random.rand(10, 10) >>> D = (D + D.T) / 2 # Make symmetric >>> np.fill_diagonal(D, 0) >>> G, A = net_knn(D, k=3, mutual=False, weighted=True) >>> G.number_of_edges() 30
- ts2net.multivariate.net_knn_approx(D, k, metric='precomputed', n_neighbors=15, weighted=False, directed=False)[source]
Approximate k-NN network using PyNNDescent.
Much faster than exact k-NN for large datasets (>1000 nodes), but may miss some nearest neighbors.
- Parameters:
D (array (n, n)) – Distance matrix (if metric=’precomputed’) OR raw feature matrix (if metric=’euclidean’, etc.)
k (int) – Number of nearest neighbors
metric (str) – ‘precomputed’ (use D as distance matrix) OR ‘euclidean’, ‘cosine’, ‘manhattan’, etc. (compute on the fly)
n_neighbors (int) – Number of neighbors for approximation (>= k, larger = more accurate)
weighted (bool) – If True, edge weights = distances
directed (bool) – If True, create directed graph
- Returns:
G (networkx.Graph or DiGraph) – Approximate k-NN network
A (array (n, n)) – Adjacency matrix
- Return type:
Tuple[Graph, ndarray]
Notes
Requires: pip install pynndescent
Speed comparison (n=10,000 nodes): - Exact k-NN: ~2 minutes - Approximate k-NN: ~3 seconds (40x faster)
Examples
>>> # For very large datasets >>> X = np.random.randn(10000, 1000) # 10k series, 1k points each >>> G, A = net_knn_approx(X, k=10, metric='euclidean')
>>> # Or with precomputed distances >>> D = ts_dist(X, method='correlation', n_jobs=-1) >>> G, A = net_knn_approx(D, k=10, metric='precomputed')
- ts2net.multivariate.net_weighted(D, threshold=None, directed=False)[source]
Complete weighted network from distance matrix.
All pairs connected with edge weight = distance.
- Parameters:
D (array (n, n)) – Distance matrix
threshold (float, optional) – Remove edges with distance > threshold
directed (bool) – If True, create directed graph
- Returns:
G (networkx.Graph or DiGraph) – Weighted network
A (array (n, n)) – Adjacency matrix (weighted)
- Return type:
Tuple[Graph, ndarray]
Examples
>>> D = np.random.rand(10, 10) >>> G, A = net_weighted(D, threshold=0.5)
- ts2net.multivariate.network_comparison_metrics(networks, names=None)[source]
Compute comparison metrics for multiple networks.
- Parameters:
networks (list of networkx.Graph) – List of networks to compare
names (list of str, optional) – Names for each network
- Returns:
metrics – Dictionary with comparison metrics: - density_similarity: Pairwise density correlations - degree_correlation: Pairwise degree sequence correlations - edge_overlap: Pairwise edge overlap (Jaccard similarity) - structural_similarity: Overall structural similarity matrix
- Return type:
dict
- ts2net.multivariate.ts_dist(X, method='correlation', n_jobs=1, executor=None, device='cpu', gpu_backend='auto', **kwargs)[source]
Calculate pairwise distance matrix between multiple time series.
- Parameters:
X (array (n_series, n_timepoints)) – Multiple time series to compare
method (str) – Distance function: ‘correlation’, ‘ccf’, ‘dtw’, ‘nmi’, ‘es’
n_jobs (int) – Number of parallel workers (-1 = all cores)
executor (str, optional) – Distributed backend:
daskorray. Overridesn_jobswhen set.device (str, default
cpu) –cpu,cuda,gpu, orauto(usesTS2NET_DEVICE).gpu_backend (str, default
auto) –torchorcupyfor GPU correlation matrices.**kwargs – Distance-specific parameters
- Returns:
D – Distance matrix (symmetric, diagonal = 0)
- Return type:
Examples
>>> import numpy as np >>> X = np.random.randn(10, 100) >>> D = ts_dist(X, method='correlation', n_jobs=-1) >>> D.shape (10, 10)
- ts2net.multivariate.ts_dist_part(X, start_idx, end_idx, method='correlation', **kwargs)[source]
Calculate partial distance matrix for HPC batch processing.
- Parameters:
X (array (n_series, n_timepoints)) – All time series
start_idx (int) – Start row index (inclusive)
end_idx (int) – End row index (exclusive)
method (str) – Distance function name
**kwargs – Distance-specific parameters
- Returns:
D_part – Partial distance matrix (rows start_idx:end_idx)
- Return type:
array (end_idx - start_idx, n_series)
Examples
>>> # On cluster node 1 >>> D_part = ts_dist_part(X, 0, 100, method='dtw') >>> np.save('D_part_0_100.npy', D_part)
- ts2net.multivariate.ts_to_windows(x, width, by=1, start=0, end=None)[source]
Extract sliding windows from a time series.
This function is equivalent to R ts2net’s ts_to_windows() and enables proximity network construction where each window becomes a node.
- Parameters:
x (array (n_points,)) – Input time series
width (int) – Window width (number of time points per window)
by (int) – Step size between consecutive windows
start (int) – Starting index (0-based)
end (int, optional) – Ending index (exclusive). If None, use len(x)
- Returns:
windows – Matrix where each row is a window
- Return type:
array (n_windows, width)
Examples
>>> x = np.sin(np.linspace(0, 4*np.pi, 100)) >>> windows = ts_to_windows(x, width=10, by=1) >>> windows.shape (91, 10)
>>> # Build proximity network from windows >>> from ts2net.multivariate import ts_dist, net_enn >>> D = ts_dist(windows, method='correlation', n_jobs=-1) >>> G, A = net_enn(D, percentile=20)
Notes
This implements the R ts2net approach for single time series: 1. Extract sliding windows 2. Treat each window as a time series 3. Calculate pairwise distances 4. Construct network (k-NN, ε-NN, etc.)
- ts2net.multivariate.ts_to_windows_labeled(x, width, by=1)[source]
Extract windows with temporal labels.
Returns both windows and their starting indices for temporal analysis.
- Parameters:
x (array) – Input time series
width (int) – Window width
by (int) – Step size
- Returns:
windows (array (n_windows, width)) – Window matrix
indices (array (n_windows,)) – Starting index of each window
- Return type:
tuple
Examples
>>> x = np.arange(100) >>> windows, indices = ts_to_windows_labeled(x, width=10, by=5) >>> indices[:5] array([ 0, 5, 10, 15, 20])
- ts2net.multivariate.ts_to_windows_list(X, width, by=1)[source]
Extract windows from multiple time series and concatenate.
- Parameters:
X (list of arrays) – List of time series
width (int) – Window width
by (int) – Step size
- Returns:
windows – All windows from all series
- Return type:
array (total_windows, width)
Examples
>>> series_list = [np.random.randn(100) for _ in range(5)] >>> windows = ts_to_windows_list(series_list, width=10, by=5)
- ts2net.multivariate.ts_window_stats(windows)[source]
Calculate statistics for each window.
Useful for feature extraction before network construction.
- Parameters:
windows (array (n_windows, width)) – Window matrix
- Returns:
stats – Dictionary with arrays of statistics: - mean, std, min, max, median - skewness, kurtosis - trend (linear regression slope)
- Return type:
dict
Examples
>>> windows = ts_to_windows(x, width=10, by=1) >>> stats = ts_window_stats(windows) >>> print(stats['mean'].shape) (n_windows,)
Distances
Distance metrics for time series analysis.
This module provides various distance metrics for comparing time series, including correlation-based, dynamic time warping, and information-theoretic measures.
- ts2net.distances.dist_matrix_normalize(D, kind='minmax')[source]
Normalize a distance matrix.
- Parameters:
D (ndarray) – Input distance matrix
kind (str) – Normalization method (‘minmax’ or ‘zscore’)
- Returns:
Normalized distance matrix
- Return type:
ndarray
- ts2net.distances.dist_percentile(D, q)[source]
Compute a percentile of the upper triangle of a distance matrix.
- Parameters:
D (ndarray) – Distance matrix
q (float) – Percentile (0-100)
- Returns:
The q-th percentile of the upper triangle values
- Return type:
float
- ts2net.distances.tsdist_ccf(X, max_lag=10)[source]
Compute distance matrix using maximum cross-correlation.
- Parameters:
X (ndarray) – Input time series array of shape (n_series, n_timesteps)
max_lag (int) – Maximum lag to consider for cross-correlation
- Returns:
Distance matrix of shape (n_series, n_series)
- Return type:
ndarray
- ts2net.distances.tsdist_cor(X, method='pearson', absolute=False)[source]
Compute distance matrix using correlation as a distance measure.
- Parameters:
X (ndarray) – Input time series array of shape (n_series, n_timesteps)
method (str) – Correlation method (‘pearson’ or ‘spearman’)
absolute (bool) – If True, use absolute value of correlation
- Returns:
Distance matrix of shape (n_series, n_series)
- Return type:
ndarray
- ts2net.distances.tsdist_dtw(X, band=None)[source]
Pairwise DTW distance matrix.
- Parameters:
X (ndarray) – Input time series array of shape (n_series, n_timesteps)
band (int | None) – Sakoe-Chiba bandwidth; None = unconstrained (Rust backend only)
- Returns:
Symmetric distance matrix of shape (n_series, n_series)
- Return type:
ndarray
Notes
Backend priority: Rust (ts2net_rs) → tslearn → pure Python. Check
ts2net.distances.dtw._BACKENDto see which is active.
- ts2net.distances.tsdist_mic(x, y)[source]
Maximal Information Coefficient (MIC) distance between two time series.
Returns
1 - MIC(x, y)so that 0 means identical dependence and 1 means independence (same convention astsdist_nmi).Requires the
minepypackage (pip install minepy). Unlike MIC, NMI is not a valid substitute — they measure different things and return different values. AnImportErroris raised rather than silently returning a different metric.- Parameters:
x (ndarray) – Input time series of equal length.
y (ndarray) – Input time series of equal length.
- Returns:
MIC distance in [0, 1].
- Raises:
ImportError – If
minepyis not installed.- Return type:
float
- ts2net.distances.tsdist_nmi(x, y, bins=32)[source]
Compute normalized mutual information between two time series.
- Parameters:
x (ndarray) – Input time series
y (ndarray) – Input time series
bins (int) – Number of bins for discretization
- Returns:
Normalized mutual information distance (0-1 range)
- Return type:
float
- ts2net.distances.tsdist_voi(x, y, bins=32)[source]
Compute variation of information between two time series.
- Parameters:
x (ndarray) – Input time series
y (ndarray) – Input time series
bins (int) – Number of bins for discretization
- Returns:
Variation of information distance
- Return type:
float
- ts2net.distances.tsdist_vr(t1, t2, tau=1.0, T=None)[source]
Compute Van Rossum distance between two spike trains.
- Parameters:
t1 (ndarray) – Arrays of spike times
t2 (ndarray) – Arrays of spike times
tau (float) – Time constant for exponential kernel
T (float | None) – Total time interval (if None, use max spike time)
- Returns:
Van Rossum distance
- Return type:
float
I/O
Polars-based Parquet ingestion for time series data.
This module provides efficient lazy-loading of time series from Parquet files using Polars, converting to NumPy arrays for use with ts2net core algorithms.
- ts2net.io_polars.load_series_from_parquet_polars(path, time_col, value_col, id_col=None, start=None, end=None, freq=None, agg='mean', tz=None, columns_extra=None)[source]
Load time series from Parquet file using Polars (lazy evaluation).
Uses lazy evaluation to minimize memory usage. Converts to NumPy arrays for compatibility with ts2net core algorithms.
- Parameters:
path (str) – Path to Parquet file or directory of Parquet files
time_col (str) – Column name for timestamps
value_col (str) – Column name for values
id_col (str, optional) – Column name for series identifier (e.g., meter_id, region) If None, returns single series as tuple (times, values)
start (str, optional) – Start timestamp filter (ISO format or parseable by Polars)
end (str, optional) – End timestamp filter (ISO format or parseable by Polars)
freq (str, optional) – Time frequency for bucketing (e.g., ‘1h’, ‘1d’, ‘15m’) Uses Polars group_by_dynamic for efficient time-based aggregation
agg (str, default 'mean') – Aggregation function: ‘mean’, ‘sum’, ‘min’, ‘max’, ‘median’, ‘first’, ‘last’
tz (str, optional) – Timezone for time_col (e.g., ‘UTC’, ‘Europe/Madrid’)
columns_extra (list[str], optional) – Additional columns to keep in output (not used for aggregation)
- Returns:
If id_col is provided: dict mapping id -> values array If id_col is None: tuple of (times, values) arrays
- Return type:
dict[str, np.ndarray] or tuple[np.ndarray, np.ndarray]
Examples
>>> # Single series >>> times, values = load_series_from_parquet_polars( ... 'data.parquet', time_col='timestamp', value_col='consumption' ... )
>>> # Multiple series by meter_id >>> series = load_series_from_parquet_polars( ... 'data.parquet', ... time_col='timestamp', ... value_col='consumption', ... id_col='meter_id', ... freq='1h', ... start='2024-01-01', ... end='2024-12-31' ... ) >>> # series = {'meter_1': np.array([...]), 'meter_2': np.array([...]), ...}
Columnar data adapters for ts2net.
Provides thin adapters that convert pandas/polars DataFrames to NumPy arrays for use with ts2net core algorithms. Core algorithms remain pure NumPy.
- ts2net.io_adapters.from_pandas(df, value_col, group_col=None, time_col=None, sort_by_time=True)[source]
Convert pandas DataFrame to NumPy arrays for ts2net.
- Parameters:
df (pd.DataFrame) – Input DataFrame
value_col (str) – Column name for time series values
group_col (str, optional) – Column name for grouping (e.g., meter_id, region) If provided, returns dict mapping group -> values array
time_col (str, optional) – Column name for timestamps (used for sorting only)
sort_by_time (bool, default True) – If True and time_col provided, sort by time
- Returns:
If group_col is None: single array of values If group_col is provided: dict mapping group -> values array
- Return type:
np.ndarray or dict[str, np.ndarray]
Examples
>>> import pandas as pd >>> df = pd.DataFrame({'timestamp': pd.date_range('2024-01-01', periods=100, freq='1h'), ... 'consumption': np.random.randn(100), ... 'meter_id': ['meter_1'] * 100}) >>> # Single series >>> values = from_pandas(df, value_col='consumption', time_col='timestamp') >>> # Multiple series >>> series = from_pandas(df, value_col='consumption', group_col='meter_id', time_col='timestamp')
- ts2net.io_adapters.from_polars(df, value_col, group_col=None, time_col=None, sort_by_time=True)[source]
Convert polars DataFrame to NumPy arrays for ts2net.
- Parameters:
df (pl.DataFrame) – Input DataFrame
value_col (str) – Column name for time series values
group_col (str, optional) – Column name for grouping (e.g., meter_id, region) If provided, returns dict mapping group -> values array
time_col (str, optional) – Column name for timestamps (used for sorting only)
sort_by_time (bool, default True) – If True and time_col provided, sort by time
- Returns:
If group_col is None: single array of values If group_col is provided: dict mapping group -> values array
- Return type:
np.ndarray or dict[str, np.ndarray]
Examples
>>> import polars as pl >>> df = pl.DataFrame({ ... 'timestamp': pl.datetime_range(pl.date(2024, 1, 1), pl.date(2024, 1, 5), '1h', eager=True), ... 'consumption': np.random.randn(97), ... 'meter_id': ['meter_1'] * 97 ... }) >>> # Single series >>> values = from_polars(df, value_col='consumption', time_col='timestamp') >>> # Multiple series >>> series = from_polars(df, value_col='consumption', group_col='meter_id', time_col='timestamp')
BSTS (Bayesian Structural Time Series)
Bayesian Structural Time Series (BSTS) decomposition and residual topology analysis.
This module provides structural decomposition of time series and network analysis of residuals to separate predictable structure from irregular dynamics.
- class ts2net.bsts.BSTSSpec(level=True, trend=False, seasonal_periods=None, robust=False, standardize_residual=True)[source]
Bases:
objectSpecification for structural time series decomposition.
- Parameters:
level (bool, default True) – Include local level component
trend (bool, default False) – Include local linear trend
seasonal_periods (list of int, optional) – Seasonal periods (e.g., [24, 168] for hourly data with daily/weekly seasonality)
robust (bool, default False) – Use Student-t errors for heavy tails (slower, more robust)
standardize_residual (bool, default True) – Standardize residual before analysis (recommended)
- level: bool = True
- robust: bool = False
- seasonal_periods: List[int] | None = None
- standardize_residual: bool = True
- trend: bool = False
- class ts2net.bsts.FeaturesResult(raw_stats, structural_stats, residual_network_stats)[source]
Bases:
objectResult of feature extraction with BSTS decomposition.
- Parameters:
raw_stats (Dict[str, Any])
structural_stats (Dict[str, Any])
residual_network_stats (Dict[str, Any])
- raw_stats
Basic statistics of raw series (mean, std, min, max, etc.)
- Type:
dict
- structural_stats
Structural component statistics (variances, seasonal strength, etc.)
- Type:
dict
- residual_network_stats
Network statistics computed on residual (HVG, NVG, transition)
- Type:
dict
- raw_stats: Dict[str, Any]
- residual_network_stats: Dict[str, Any]
- structural_stats: Dict[str, Any]
- ts2net.bsts.decompose(series, spec)[source]
Decompose time series into structural components using state space model.
Uses statsmodels state space models for fast MLE estimation.
- Parameters:
series (array) – Input time series
spec (BSTSSpec) – Decomposition specification
- Returns:
Components, residual, and variance estimates
- Return type:
DecompositionResult
- Raises:
ImportError – If statsmodels is not installed
ValueError – If series is too short or constant
- ts2net.bsts.features(series, methods=None, bsts=None, window=None, nvg_limit=None)[source]
Extract features from time series with optional BSTS decomposition.
If BSTS is enabled, decomposes series and analyzes residual with network methods. If BSTS is disabled, analyzes raw series.
- Parameters:
series (array) – Input time series
methods (list of str, optional) – Network methods to apply: ‘hvg’, ‘nvg’, ‘transition’ Default: [‘hvg’, ‘transition’]
bsts (BSTSSpec, optional) – BSTS decomposition specification. If None, analyzes raw series.
window (int, optional) – Window size for windowed analysis. If None, analyzes full series.
nvg_limit (int, optional) – Horizon limit for NVG (default: 3000)
- Returns:
Three blocks: raw_stats, structural_stats, residual_network_stats
- Return type:
Examples
>>> from ts2net.bsts import features, BSTSSpec >>> spec = BSTSSpec(level=True, seasonal_periods=[24, 168]) >>> result = features(x, methods=['hvg', 'transition'], bsts=spec) >>> print(result.structural_stats['seasonal_strength']) >>> print(result.residual_network_stats['hvg']['avg_degree'])
Temporal CNN
Temporal CNN for time series feature extraction.
Provides a simple 1D dilated CNN for fast, stable feature extraction from time series windows.
- ts2net.temporal_cnn.temporal_cnn_embeddings(x, window, stride, *, channels=(32, 64, 64), kernel_size=5, dilations=(1, 2, 4), dropout=0.1, device='cpu', batch_size=256, seed=7)[source]
Compute per-window embeddings with a small dilated 1D CNN.
- Parameters:
x (NDArray[float64]) – Array of shape (n, f) or (n,). For multivariate, f is number of features.
window (int) – Window length in time steps.
stride (int) – Step between windows.
channels (Tuple[int, ...]) – Output channels per conv block. Length must match dilations.
kernel_size (int) – Kernel size for each conv.
dilations (Tuple[int, ...]) – Dilation per block. Length must match channels length.
dropout (float) – Dropout rate.
device (str) – Torch device string (‘cpu’ or ‘cuda’).
batch_size (int) – Batch size for inference.
seed (int) – Random seed for determinism.
- Returns:
Array of shape (n_windows, channels[-1]) with embeddings.
- Raises:
ImportError – If PyTorch is not installed.
ValueError – If input shape is invalid or parameters don’t match.
- Return type:
NDArray[float64]
CLI
Configuration
Configuration schemas for ts2net YAML-based pipeline.
Provides type-safe, validated configuration classes using dataclasses.
- class ts2net.config.BSTSConfig(enabled=False, level=True, trend=False, seasonal_periods=None, robust=False, standardize_residual=True, max_points=10000, window=None)[source]
Bases:
objectBSTS decomposition configuration.
- Parameters:
enabled (bool)
level (bool)
trend (bool)
seasonal_periods (List[int] | None)
robust (bool)
standardize_residual (bool)
max_points (int)
window (int | None)
- enabled: bool = False
- level: bool = True
- max_points: int = 10000
- robust: bool = False
- seasonal_periods: List[int] | None = None
- standardize_residual: bool = True
- trend: bool = False
- window: int | None = None
- class ts2net.config.DatasetConfig(name, path, id_col=None, time_col='timestamp', value_col='value', start=None, end=None, tz=None)[source]
Bases:
objectDataset configuration.
- Parameters:
name (str)
path (str)
id_col (str | None)
time_col (str)
value_col (str)
start (str | None)
end (str | None)
tz (str | None)
- end: str | None = None
- id_col: str | None = None
- name: str
- path: str
- start: str | None = None
- time_col: str = 'timestamp'
- tz: str | None = None
- value_col: str = 'value'
- class ts2net.config.GraphsConfig(hvg=<factory>, nvg=<factory>, recurrence=<factory>, transition=<factory>)[source]
Bases:
objectGraph methods configuration.
- Parameters:
hvg (HVGConfig)
nvg (NVGConfig)
recurrence (RecurrenceConfig)
transition (TransitionConfig)
- classmethod from_dict(data)[source]
Create GraphsConfig from dictionary.
- Parameters:
data (Dict[str, Any])
- Return type:
- recurrence: RecurrenceConfig
- transition: TransitionConfig
- class ts2net.config.HVGConfig(enabled=False, output='stats', weighted=False, weight_mode=None, limit=None, directed=False, backend='auto')[source]
Bases:
objectHorizontal Visibility Graph configuration.
- Parameters:
enabled (bool)
output (str)
weighted (bool)
weight_mode (str | None)
limit (int | None)
directed (bool)
backend (str)
- backend: str = 'auto'
- directed: bool = False
- enabled: bool = False
- limit: int | None = None
- output: str = 'stats'
- weight_mode: str | None = None
- weighted: bool = False
- class ts2net.config.LoggingConfig(log_errors=True, error_path=None)[source]
Bases:
objectLogging configuration.
- Parameters:
log_errors (bool)
error_path (str | None)
- error_path: str | None = None
- log_errors: bool = True
- class ts2net.config.NVGConfig(enabled=False, output='stats', weighted=False, weight_mode=None, limit=None, max_edges=None, max_edges_per_node=None, max_memory_mb=None, backend='auto')[source]
Bases:
objectNatural Visibility Graph configuration.
- Parameters:
enabled (bool)
output (str)
weighted (bool)
weight_mode (str | None)
limit (int | None)
max_edges (int | None)
max_edges_per_node (int | None)
max_memory_mb (int | None)
backend (str)
- backend: str = 'auto'
- enabled: bool = False
- limit: int | None = None
- max_edges: int | None = None
- max_edges_per_node: int | None = None
- max_memory_mb: int | None = None
- output: str = 'stats'
- weight_mode: str | None = None
- weighted: bool = False
- class ts2net.config.OutputConfig(format='parquet', path='results/output.parquet', overwrite=True, mode=None)[source]
Bases:
objectOutput configuration.
- Parameters:
format (str)
path (str)
overwrite (bool)
mode (str | None)
- format: str = 'parquet'
- mode: str | None = None
- overwrite: bool = True
- path: str = 'results/output.parquet'
- class ts2net.config.PipelineConfig(dataset, graphs, output, sampling=<factory>, windows=<factory>, bsts=<factory>, logging=<factory>)[source]
Bases:
objectComplete pipeline configuration.
- Parameters:
dataset (DatasetConfig)
graphs (GraphsConfig)
output (OutputConfig)
sampling (SamplingConfig)
windows (WindowsConfig)
bsts (BSTSConfig)
logging (LoggingConfig)
- bsts: BSTSConfig
- dataset: DatasetConfig
- classmethod from_dict(data)[source]
Create PipelineConfig from dictionary (e.g., from YAML).
- Parameters:
data (Dict[str, Any])
- Return type:
- classmethod from_yaml(yaml_path)[source]
Load configuration from YAML file.
- Parameters:
yaml_path (str | Path)
- Return type:
- graphs: GraphsConfig
- logging: LoggingConfig
- output: OutputConfig
- sampling: SamplingConfig
- windows: WindowsConfig
- class ts2net.config.RecurrenceConfig(enabled=False, output='stats', rule='knn', k=10, m=None, tau=1, epsilon=0.1, metric='euclidean', backend='auto')[source]
Bases:
objectRecurrence Network configuration.
- Parameters:
enabled (bool)
output (str)
rule (str)
k (int)
m (int | None)
tau (int)
epsilon (float)
metric (str)
backend (str)
- backend: str = 'auto'
- enabled: bool = False
- epsilon: float = 0.1
- k: int = 10
- m: int | None = None
- metric: str = 'euclidean'
- output: str = 'stats'
- rule: str = 'knn'
- tau: int = 1
- class ts2net.config.SamplingConfig(frequency=None, agg='mean', resample=False)[source]
Bases:
objectSampling/resampling configuration.
- Parameters:
frequency (str | None)
agg (str)
resample (bool)
- agg: str = 'mean'
- frequency: str | None = None
- resample: bool = False
- class ts2net.config.TransitionConfig(enabled=False, output='stats', symbolizer='ordinal', order=3, n_states=None, partition_mode=False, backend='auto')[source]
Bases:
objectTransition Network configuration.
- Parameters:
enabled (bool)
output (str)
symbolizer (str)
order (int)
n_states (int | None)
partition_mode (bool)
backend (str)
- backend: str = 'auto'
- enabled: bool = False
- n_states: int | None = None
- order: int = 3
- output: str = 'stats'
- partition_mode: bool = False
- symbolizer: str = 'ordinal'
Factory
Graph builder factory for creating network builders from configuration.
Uses dispatch dictionary pattern for clean, extensible graph creation.
- ts2net.factory.aggregate_stats(stats, aggregate)[source]
Aggregate statistics using dispatch pattern.
- Parameters:
stats (dict) – Statistics dictionary from graph builder
aggregate (str) – Aggregation function: ‘mean’, ‘std’, ‘min’, ‘max’
- Returns:
Aggregated statistic value
- Return type:
float
- ts2net.factory.build_graph_from_config(series, graph_type, config, include_triangles=False)[source]
Build a graph from configuration and return statistics.
- Parameters:
series (array) – Input time series
graph_type (str) – Graph type: ‘hvg’, ‘nvg’, ‘recurrence’, or ‘transition’
config (GraphConfig) – Configuration object for the graph type
include_triangles (bool) – Whether to include triangle counting in stats (computationally expensive)
- Returns:
Graph statistics dictionary
- Return type:
dict
- ts2net.factory.create_graph_builder(graph_type, config, n_points=None)[source]
Create a graph builder from configuration using dispatch pattern.
- Parameters:
graph_type (str) – Graph type: ‘hvg’, ‘nvg’, ‘recurrence’, or ‘transition’
config (GraphConfig) – Configuration object for the graph type
n_points (int, optional) – Number of points in series (used for safety checks)
- Returns:
Configured graph builder instance
- Return type:
GraphBuilder
- Raises:
ValueError – If graph_type is unknown or configuration is invalid
- ts2net.factory.create_recurrence_builder(config, n_points=None)[source]
Create RecurrenceNetwork builder from configuration.
- Parameters:
config (RecurrenceConfig)
n_points (int | None)
- Return type:
- ts2net.factory.create_transition_builder(config)[source]
Create TransitionNetwork builder from configuration.
- Parameters:
config (TransitionConfig)
- Return type:
Spatial
Spatial analysis utilities for ts2net.
This module provides functions for spatial weights matrix generation.