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: object

Result 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: object

Specification 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: object

Full 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]
significant_edges()[source]

Edges passing the significance threshold.

Return type:

List[CausalEdgeResult]

summary()[source]

Plain-text causal report.

Return type:

str

to_markdown()[source]

Markdown causal report.

Return type:

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: object

Configuration 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'
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: object

Evidence bundle for decision support: graph + optional causal/dynamic context.

Parameters:
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]
summary()[source]
Return type:

str

title: str
to_dict()[source]
Return type:

dict[str, Any]

to_markdown()[source]
Return type:

str

class ts2net.DynamicAnalysisResult(sequence, regime, anomalies, transition_anomalies, persistence, churn, communities, roles, attribution=<factory>, method='hvg', window=50, step=1)[source]

Bases: object

Full 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
summary()[source]

Plain-text dynamic analysis report.

Return type:

str

to_markdown()[source]

Markdown dynamic analysis report.

Return type:

str

transition_anomalies: NDArray[float64]
window: int = 50
class ts2net.DynamicChangeReport(result, title='Dynamic change report')[source]

Bases: object

Regime breaks, edge persistence, and attribution from dynamic analysis.

Parameters:
result: DynamicAnalysisResult
summary()[source]
Return type:

str

title: str = 'Dynamic change report'
to_markdown()[source]
Return type:

str

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: object

Configuration 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: object

Why 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
summary()[source]
Return type:

str

target: str | int
weight: float
class ts2net.FCIResult(pag, skeleton, separating_sets, variable_names, alpha, n_obs, method='fci', metadata=<factory>)[source]

Bases: object

Output 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
to_networkx()[source]

Return the PAG with endpoint marks on edges.

Return type:

DiGraph

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: object

Lightweight 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: object

Human-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
summary()[source]
Return type:

str

title: str
to_dict()[source]
Return type:

dict[str, Any]

to_markdown()[source]
Return type:

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: SklearnBuildMixin

Horizontal 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. None means 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); returns self for method chaining.

Parameters:

x (array-like of shape (n,)) – Input time series.

Returns:

self

Return type:

HVG

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

in_degree_sequence()[source]

In-degree sequence (only valid for directed graphs)

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}")
out_degree_sequence()[source]

Out-degree sequence (only valid for directed graphs)

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: object

Incrementally 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:

AppendResult

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:

IncrementalHVG

limit: int | None = None
property n_edges: int
property n_nodes: int
stats()[source]

Summary statistics for the current graph.

Return type:

dict[str, float]

to_graph()[source]

Current graph snapshot.

Return type:

Graph

property values: NDArray[float64]
weighted: bool = False
class ts2net.MultiplexGraph(layers=<factory>, n_nodes=0)[source]

Bases: object

Container 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.

union takes max weight per edge; intersection requires all layers; sum adds 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]

layer_names()[source]
Return type:

list[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: object

Multiscale 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:

MultiscaleGraphs

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]
stats()[source]

Get full statistics at each scale.

Returns:

Dictionary mapping scale to statistics dictionary

Return type:

dict[int, dict]

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: SklearnBuildMixin

Natural 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); returns self for method chaining.

Parameters:

x (array-like of shape (n,)) – Input time series.

Returns:

self

Return type:

NVG

degree_sequence()[source]

Node degree sequence — shape (n_nodes,).

Return type:

NDArray[int64]

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: Protocol

Protocol implemented by all network graph builders.

build(x)[source]
Parameters:

x (NDArray[float64])

Return type:

NetworkBuilder

degree_sequence()[source]
Return type:

NDArray[int64]

fit(x)[source]
Parameters:

x (NDArray[float64])

Return type:

NetworkBuilder

fit_transform(x)[source]
Parameters:

x (NDArray[float64])

Return type:

Graph

property n_edges: int
property n_nodes: int
stats(include_triangles=False)[source]
Parameters:

include_triangles (bool)

Return type:

dict

transform()[source]
Return type:

Graph

class ts2net.NetworkFeatureExtractor(method='hvg', output='stats', features=None, prefix=None, **builder_kwargs)[source]

Bases: BaseEstimator, TransformerMixin

Extract 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=2000 for NVG, rule="knn", k=5 for 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:

NetworkFeatureExtractor

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 MetadataRequest encapsulating 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

transform(X)[source]

Extract network features for each time series.

Parameters:

X (NDArray[float64])

Return type:

NDArray[float64]

class ts2net.NetworkFeatureSelector(k=10, score_func='mutual_info', feature_names=None)[source]

Bases: BaseEstimator, TransformerMixin

Select top-k network features using univariate scoring.

Intended for use after NetworkFeatureExtractor or RollingNetworkFeatureExtractor in 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(X, y)[source]
Parameters:
  • X (NDArray[float64])

  • y (NDArray[Any])

Return type:

NetworkFeatureSelector

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 MetadataRequest encapsulating 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

transform(X)[source]
Parameters:

X (NDArray[float64])

Return type:

NDArray[float64]

class ts2net.NodeRoleSummary(node, role, degree, betweenness=None, anomaly=False, notes='')[source]

Bases: object

Role 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, ValueError

Raised 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: object

Output 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
to_networkx()[source]

Return the oriented CPDAG.

Return type:

DiGraph

variable_names: List[str]
class ts2net.PerformanceContract(method, time_complexity, memory_complexity, recommended_output, notes='')[source]

Bases: object

Expected 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
summary()[source]

One-line scaling summary.

Return type:

str

time_complexity: str
class ts2net.PipelineConfig(dataset, graphs, output, sampling=<factory>, windows=<factory>, bsts=<factory>, logging=<factory>)[source]

Bases: object

Complete pipeline configuration.

Parameters:
bsts: BSTSConfig
dataset: DatasetConfig
classmethod from_dict(data)[source]

Create PipelineConfig from dictionary (e.g., from YAML).

Parameters:

data (Dict[str, Any])

Return type:

PipelineConfig

classmethod from_yaml(yaml_path)[source]

Load configuration from YAML file.

Parameters:

yaml_path (str | Path)

Return type:

PipelineConfig

graphs: GraphsConfig
logging: LoggingConfig
output: OutputConfig
sampling: SamplingConfig
to_dict()[source]

Convert configuration to dictionary.

Return type:

Dict[str, Any]

windows: WindowsConfig
class ts2net.Provenance(method, parameters=<factory>, window=None, n_series=None, n_points=None)[source]

Bases: object

How 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: SklearnBuildMixin

Recurrence 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. None means 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:

RecurrenceNetwork

degree_sequence()[source]

Node degree sequence — shape (n_nodes,).

Return type:

NDArray[int64]

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: object

Graph 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]
churn()[source]

Edge churn between consecutive graphs.

Return type:

dict[str, NDArray[float64]]

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:

RollingGraphSequence

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, TransformerMixin

Extract 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(X, y=None)[source]
Parameters:
  • X (NDArray[float64])

  • y (NDArray[Any] | None)

Return type:

RollingNetworkFeatureExtractor

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 MetadataRequest encapsulating 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

transform(X)[source]
Parameters:

X (NDArray[float64])

Return type:

NDArray[float64]

class ts2net.SINDyResult(model, coefficients, feature_names, state_names, t=None, spec=<factory>, backend_used='pysindy')[source]

Bases: object

Outcome 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]
equations()[source]

Human-readable ODE right-hand sides (one per state).

Return type:

list[str]

feature_names: list[str]
model: Any
simulate(x0, t)[source]

Integrate the discovered model from x0 over t.

Parameters:
  • x0 (NDArray[float64])

  • t (NDArray[float64])

Return type:

NDArray[float64]

spec: SINDySpec
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: object

Configuration 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: SklearnBuildMixin

Transition Network (Ordinal Partition Network).

The time series is symbolised — each subsequence of length order+1 is 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=3 gives 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:

TransitionNetwork

degree_sequence()[source]

Node degree sequence — shape (n_nodes,).

Return type:

NDArray[int64]

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: Exception

Base 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, ValueError

Raised 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: object

Directed 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]
summary()[source]

Plain-text summary of visibility asymmetry.

Return type:

str

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=None uses raw series).

  • tau (int) – Embedding dimension and delay (m=None uses 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 NearestNeighbors with metric='precomputed'. For very large panels in raw feature space, prefer net_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 G directly, or x (univariate) to run dynamic analysis, or multivariate with causal for 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:

DecisionPackage

ts2net.build_dynamic_change_report(result, *, title=None)[source]

Wrap DynamicAnalysisResult as a change report.

Parameters:
Return type:

DynamicChangeReport

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:

GraphReport

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 dask or ray for 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 aggregate is 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 aggregate is 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 directionality indices.

Return type:

dict

ts2net.causal_strength(G, source, target, weight='weight')[source]

Path-based causal strength from source to target.

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.

Parameters:
  • X (array (n_series, n_points)) – Panel of univariate series (rows = series).

  • method ({"pearson", "spearman", "kendall", "dcor"}) – Correlation measure.

Returns:

C – Symmetric correlation matrix with unit diagonal.

Return type:

array (n_series, n_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 i connects to node j when |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 epsilon is 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") – zscore flags large jumps in first differences. cusum uses 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:

VisibilityAsymmetryResult

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: threshold or peaks (see events_from_ts).

  • thresh (float, optional) – Detection threshold.

  • min_separation (int) – Minimum samples between events.

  • edge_rule ({"consecutive", "window"}) – consecutive links adjacent events; window links all pairs within max_interval.

  • max_interval (int) – Maximum time gap for edge_rule="window".

Returns:

  • G (networkx.Graph) – Nodes are event indices with time attribute.

  • 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 q

from 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:

EdgeExplanation

ts2net.explain_edges_from_causal(result)[source]

Convert causal workflow edges to EdgeExplanation rows.

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:

FCIResult

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:

FCIResult

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:

FeaturesResult

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 dt when 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.backend selects rust, pysindy, or auto (Rust when ts2net_rs is built).

Returns:

Fitted model, coefficient matrix, and helpers.

Return type:

SINDyResult

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:

PerformanceContract

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 x Granger-causes y.

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") – linear uses OLS/VAR F-tests (requires statsmodels). nonlinear uses 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 returns mse_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 series i Granger-causes series j.

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, or significance (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) - 1 for 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.has_pynndescent()[source]
Return type:

bool

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, or pyarrow.RecordBatchReader. Requires pyarrow (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_col is provided.

Yields:
  • chunk_index (int)

  • values (array) – Chunk of value_col as 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 polars package (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_col is provided.

Yields:
  • chunk_index (int)

  • values (array) – Chunk of value_col as 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 as ts_to_windows).

  • end (int, optional) – Slice bounds on x (same semantics as ts_to_windows).

  • copy (bool, default False) – If True, copy each window slice (safer if x is 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:

MultiplexGraph

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 / NVG builders.

  • nvg_kwargs (dict, optional) – Arguments passed to HVG / NVG builders.

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; None if 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).

Parameters:

X (array (n_series, n_points)) – Panel of time series.

Returns:

P – Partial correlation matrix.

Return type:

array (n_series, 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:
  • X (array (n_series, n_points))

  • 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:

PCResult

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:

PCResult

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_density if 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 epsilon when 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. rqa contains 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 **kwargs override spec fields.

  • **kwargs – Override any CausalWorkflowSpec field by name.

Returns:

Graph, edge table, matrices, metrics, and report helpers.

Return type:

CausalAnalysisResult

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 **kwargs override spec fields.

  • **kwargs – Override any DynamicWorkflowSpec field by name.

Returns:

Sequence, metrics, and report helpers.

Return type:

DynamicAnalysisResult

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 xy.

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") – pvalue picks the lag with the smallest p-value. aic / bic pick 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 optionally aic/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 x to y.

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.

Parameters:
  • X (array (n_series, n_points))

  • method (str) – euclidean, correlation, spearman, or any ts_dist method.

  • n_jobs (int) – Parallel workers for supported methods.

Return type:

NDArray[float64]

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:
  • X (array (n_series, n_points))

  • 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 i is added when the discovered equation for state_i has a term involving state_j above threshold.

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 weight holds 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_eq is 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 source is 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_lag returns a dict keyed by lag. max / mean aggregate the weight matrices across lags.

  • n_jobs (int, default 1) – Parallel workers passed to the underlying network builder.

  • **kwargs – Extra arguments for transfer_entropy_network or granger_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 combine is max or mean.

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 Graph to 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 Graph to a PyG Data object.

Parameters:
  • graph (Graph) – ts2net graph (integer node indices recommended).

  • node_features (array (n_nodes, n_features), optional) – Node feature matrix. Defaults to in-degree column vector.

  • y (float or int, optional) – Graph-level label (stored as data.y).

  • graph_label (float or int, optional) – Alias for y.

Returns:

PyG graph with x, edge_index, optional edge_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.stats or build_windows output).

  • 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: SklearnBuildMixin

Horizontal 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. None means 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); returns self for method chaining.

Parameters:

x (array-like of shape (n,)) – Input time series.

Returns:

self

Return type:

HVG

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

in_degree_sequence()[source]

In-degree sequence (only valid for directed graphs)

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}")
out_degree_sequence()[source]

Out-degree sequence (only valid for directed graphs)

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: SklearnBuildMixin

Natural 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); returns self for method chaining.

Parameters:

x (array-like of shape (n,)) – Input time series.

Returns:

self

Return type:

NVG

degree_sequence()[source]

Node degree sequence — shape (n_nodes,).

Return type:

NDArray[int64]

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: Protocol

Protocol implemented by all network graph builders.

build(x)[source]
Parameters:

x (NDArray[float64])

Return type:

NetworkBuilder

degree_sequence()[source]
Return type:

NDArray[int64]

fit(x)[source]
Parameters:

x (NDArray[float64])

Return type:

NetworkBuilder

fit_transform(x)[source]
Parameters:

x (NDArray[float64])

Return type:

Graph

property n_edges: int
property n_nodes: int
stats(include_triangles=False)[source]
Parameters:

include_triangles (bool)

Return type:

dict

transform()[source]
Return type:

Graph

class ts2net.api.RecurrenceNetwork(m=None, tau=1, rule='knn', k=5, epsilon=0.1, metric='euclidean', only_degrees=False, output='edges')[source]

Bases: SklearnBuildMixin

Recurrence 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. None means 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:

RecurrenceNetwork

degree_sequence()[source]

Node degree sequence — shape (n_nodes,).

Return type:

NDArray[int64]

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: SklearnBuildMixin

Transition Network (Ordinal Partition Network).

The time series is symbolised — each subsequence of length order+1 is 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=3 gives 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:

TransitionNetwork

degree_sequence()[source]

Node degree sequence — shape (n_nodes,).

Return type:

NDArray[int64]

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.

class ts2net.core.SKMixin[source]

Bases: object

Mixin class for scikit-learn compatibility.

get_params(deep=True)[source]

Get parameters for this estimator.

set_params(**params)[source]

Set parameters for this estimator.

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]

ts2net.core.motif_summary(G)[source]
Parameters:

G (Graph | DiGraph)

Return type:

dict

ts2net.core.njit(*args, **kwargs)[source]

Dummy decorator when numba is not available.

ts2net.core.small_world_summary(G)[source]
Parameters:

G (Graph | DiGraph)

Return type:

dict

ts2net.core.triangle_count(G)[source]
Parameters:

G (Graph)

Return type:

int

ts2net.core.undirected_4node_motifs(G, max_samples=None, seed=3363)[source]
Parameters:
  • G (Graph)

  • max_samples (int | None)

  • seed (int)

Return type:

dict

ts2net.core.wedge_count(G)[source]
Parameters:

G (Graph)

Return type:

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: object

Container 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:

TSGraph

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: object

Container 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:

TSGraph

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: dask or ray. Overrides n_jobs when set.

  • device (str, default cpu) – cpu, cuda, gpu, or auto (uses TS2NET_DEVICE).

  • gpu_backend (str, default auto) – torch or cupy for GPU correlation matrices.

  • **kwargs – Distance-specific parameters

Returns:

D – Distance matrix (symmetric, diagonal = 0)

Return type:

array (n_series, n_series)

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._BACKEND to 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 as tsdist_nmi).

Requires the minepy package (pip install minepy). Unlike MIC, NMI is not a valid substitute — they measure different things and return different values. An ImportError is 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 minepy is 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: object

Specification 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: object

Result 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:

FeaturesResult

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: object

BSTS 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: object

Dataset 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: object

Graph methods configuration.

Parameters:
classmethod from_dict(data)[source]

Create GraphsConfig from dictionary.

Parameters:

data (Dict[str, Any])

Return type:

GraphsConfig

hvg: HVGConfig
nvg: NVGConfig
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: object

Horizontal 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: object

Logging 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: object

Natural 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: object

Output 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: object

Complete pipeline configuration.

Parameters:
bsts: BSTSConfig
dataset: DatasetConfig
classmethod from_dict(data)[source]

Create PipelineConfig from dictionary (e.g., from YAML).

Parameters:

data (Dict[str, Any])

Return type:

PipelineConfig

classmethod from_yaml(yaml_path)[source]

Load configuration from YAML file.

Parameters:

yaml_path (str | Path)

Return type:

PipelineConfig

graphs: GraphsConfig
logging: LoggingConfig
output: OutputConfig
sampling: SamplingConfig
to_dict()[source]

Convert configuration to dictionary.

Return type:

Dict[str, Any]

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: object

Recurrence 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: object

Sampling/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: object

Transition 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'
class ts2net.config.WindowsConfig(enabled=False, size=None, step=None)[source]

Bases: object

Windowing configuration.

Parameters:
  • enabled (bool)

  • size (int | None)

  • step (int | None)

enabled: bool = False
size: int | None = None
step: int | None = None

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_hvg_builder(config)[source]

Create HVG builder from configuration.

Parameters:

config (HVGConfig)

Return type:

HVG

ts2net.factory.create_nvg_builder(config)[source]

Create NVG builder from configuration.

Parameters:

config (NVGConfig)

Return type:

NVG

ts2net.factory.create_recurrence_builder(config, n_points=None)[source]

Create RecurrenceNetwork builder from configuration.

Parameters:
Return type:

RecurrenceNetwork

ts2net.factory.create_transition_builder(config)[source]

Create TransitionNetwork builder from configuration.

Parameters:

config (TransitionConfig)

Return type:

TransitionNetwork

Spatial

Spatial analysis utilities for ts2net.

This module provides functions for spatial weights matrix generation.

ts2net.core.spatial.knn_weights(coords, k)[source]

Generate spatial weights matrix based on k-nearest neighbors.

Parameters:
  • coords (ndarray) – Coordinate array of shape (n, d)

  • k (int) – Number of nearest neighbors

Returns:

Weights matrix of shape (n, n)

Return type:

ndarray

ts2net.core.spatial.radius_weights(coords, radius)[source]

Generate spatial weights matrix based on radius threshold.

Parameters:
  • coords (ndarray) – Coordinate array of shape (n, d)

  • radius (float) – Distance threshold for connectivity

Returns:

Weights matrix of shape (n, n)

Return type:

ndarray