Skip to content

algorithm

OpenDGM algorithm provides pre-made algorithms that look for objects of interest in cardiac data.

There are algorithms for: - Find cycles in a graph - Find focal sources in a graph - Create a vector field - Apply basic phasemapping to find rotors - Apply extended phasemapping to find reentries through phase defects

Algorithm

Bases: ABC, PropertyMixin

Base class for graph algorithms implementation. Intended for use by a backend (third party) library as the basis for algorithmic solutions.

Before applying algorithms from the library, it is necessary to create an internal graph representation that will meet the requirements of the library.

run() abstractmethod

Run algorithm.

AreaFlows

Bases: NodeFlows

radius = 10 instance-attribute

__init__(graph)

filter_area_paths(node_source, area_nodes)

Filter area nodes that have no in-area connection to the source node. i.e. all area nodes for which the source node has no connection into said area node are removed.

Parameters:

Name Type Description Default
node_source int

the graph nodes for which we want to filter connections

required
area_nodes ndarray

all nodes within its area

required

Returns:

Type Description
ndarray

np.ndarray: filtered area nodes

run()

Calculate the in-, out- and contained degree of each node to an area within radius.

Returns:

Type Description
tuple[ndarray, ndarray, ndarray]

tuple[np.ndarray]: in-, out- and contained degree

set_radius(radius)

Boundary

arrows = None instance-attribute

connections = None instance-attribute

hist = [] instance-attribute

ids = np.array(ids) instance-attribute

index = 0 instance-attribute

label = '' instance-attribute

period = 0 instance-attribute

points = np.array(points[ids]).astype(float) instance-attribute

projection = None instance-attribute

scalars = np.array(scalars[ids]) instance-attribute

section_count = 12 instance-attribute

sections = None instance-attribute

__init__(ids, points, scalars)

build_sections(t=0, period=-1, amount=12, geo_center=np.zeros(3))

calc_index(period)

Given an array of edges ex [1, 1, 1, -1, 0, 1, 1, -1, -1] between sections, calculate the sum of phase differences between each two consecutive lats

extend(points, triangles, scalars, distance=0)

get_arrows_object()

Get edge visualization around a boundary with arrows colored by direction. Clockwise, counterclockwise or neutral.

Returns:

Name Type Description
list EdgeBuilder

List of arrows

get_center()

get_label_object()

reduce(distance=5)

set_period(period)

to_single_scalars(t=0)

Convert irregular data to single LATs For each node keeping the first LAT after time t

BoundaryFilter

Bases: PolydataFilter

get_boundaries(coords, triangles, scalars, min_points=3) staticmethod

label(boundaries, maptype) staticmethod

Automatic labeling of anatomical boundaries based on default orientation of CARTO and Rhythmia exported data. The three largest boundaries are labeled "MV", "LPV" and "RPV". Any remaining boundaries are labeled "scar".

Parameters:

Name Type Description Default
boundaries list[Boundary]

List of boundaries to label.

required
maptype str

Mapping system. Options are "carto" or "rhythmia".

required

CompleteSearch

Bases: NKAlgorithm

Searching all possible cycles with number of nodes greater than 2.

algorithm = DijkstraShortestPath instance-attribute

min_length = 0 instance-attribute

search_algorithms = {'dijkstra': DijkstraShortestPath, 'bfs': BreadthFirstSearch} instance-attribute

search_type = 'shortest' instance-attribute

__init__(graph)

compute_weight_matrix()

Calculate weight matrix. The weight matrix has, for each set of two nodes a value of 0 if the nodes are not connected. If the nodes are connected, the value in the matrix is the weight of the edge connectint them.

Returns:

Type Description
ndarray

np.ndarray[N, N]: weight matrix

cycle_pairs()

For each node, find all edges connecting to it (in-neighbors). Using the distance matrix, verify if a cycle exists between with a distance larger than min_distance. If self.search_type is 'shortest', only return the closest in-neighbor, else return all in-neighbors.

Returns:

Type Description
tuple[ndarray, ndarray]

tuple[np.ndarrays]: sources and targets

run()

Find all possible cycles in the graph.

Returns:

Name Type Description
Dataframe DataFrame

Dataframe of cycles.

set_algorithm(algorithm)

Default: 'dijkstra'

set_min_length(min_length)

minimum length of a valid cycle found by the cycle search Default: 0

set_search_type(search_type)

Default: 'shortest'

to_nk_graph(graph)

DirectedHelmholtz

Bases: Algorithm

Performs the Directed Helmholtz decomposition for valued (weighted) directed graphs. The decomposition decomposes the edge weights X into a curl-free X_G and gradient-free X_C component.

The algorithm employs the cut method, which calculates X_G from the cut matrix D of the graph by minimizing the difference (X - X_C).(X - X_C)^T with the restriction that D.X_C = 0, a condition that translates into the incoming edge values of X_C being equal to the outgoing edge values (divergence-free). X_G = X - X_C has the property that the sum of edge values along every cycle equals 0 (curl-free).

Taken from DOI: 10.13140/RG.2.2.18011.64807

graph = graph instance-attribute

matrix = None instance-attribute

method = 'cut' instance-attribute

projector = None instance-attribute

use_points = False instance-attribute

__init__(graph)

calc_cut_matrix(incidence_matrix) staticmethod

Given a spanning tree, the cut matrix (n_nodes x n_edges) is the collection of directional edges (+-1) contained in the cut for each node, where only nodes containing one edge from the spanning tree are considered. The cut matrix can be obtained by removing one row from the incidence matrix, yielding a matrix with linearly independent rows.

Parameters:

Name Type Description Default
incidence_matrix ndarray[n_nodes, n_edges]

Incidence matrix.

required

Returns:

Type Description
ndarray

np.ndarray[n_cuts, n_edges]: Cut matrix.

calc_cycle_matrix(span_forest)

The cycle matrix (n_cycles x n_edges) contains for each elementary cycle (cycle basis) in the graph the direction (+-1) of the edges contained in this cycle. The cycle basis can be used to obtain all possible cycles in the graph. This cycle basis can be constructed by calculating the undirected Spanning Tree (span_forest), consisting of the birth edges of the graph, iteratively adding the remaining edges (death edges), and searching for cycles for each iteration. As each death edge adds one elementary cycle to the graph, the number of cycles is equal to the number of death edges.

Parameters:

Name Type Description Default
span_forest ndarray[n_edges, 2]

Spanning forest

required

Returns:

Type Description
ndarray

np.ndarray[n_cycles, n_edges]: Cycle matrix.

calc_incidence_matrix()

The incidence matrices with dimensions n_nodes x n_edges contains for each directed edge a -1 for the node at the base and +1 for the node at the tip of the edge.

Returns:

Type Description
ndarray

np.ndarray[n_nodes, n_edges]: Incidence matrix.

calc_matrix()

calc_projector()

Matrix that projects the edge values to their gradient-free subspace.

This matrix is obtained from the generalized restricted least square estimation of (X - X_C).(X - X_C).T with the restriction D.X_C = 0. The reduced laplacian matrix DD^T has the same eigenvalues as the laplacian matrix II^T but has linearly independent rows (with D the cut matrix and I the incidence matrix).

Matrix that projects the edge values to their curl-free subspace. This matrix is obtained from the generalized restricted least square estimation of (X - X_G).(X - X_G).T with the restriction C.X_G = 0. The cycle overlap matrix CC^T contains the lengths of the elementary cycles on the diagonal and the signed overlap of two cycles for the off diagonal elements.

Returns:

Type Description
ndarray

np.ndarray[n_edges, n_edges]: Projection matrix.

get_undirected_cycle(graph, source, target) staticmethod

Calculates the cycle starting from a source node and ending in a target node from a graph where the connection between the source node and target node is missing.

Parameters:

Name Type Description Default
source int

Source node.

required
target int

Target node.

required

Returns:

Type Description
ndarray

np.ndarray[n_cycle_edges, 2]: Edges of the undirected cycle.

mask_approx_zero(edges, edge_scalar, threshold=0.05) staticmethod

Mask edge values that are close to zero using a threshold.

Parameters:

Name Type Description Default
edges ndarray[n_edges, 2]

Edges of the graph.

required
edge_scalar ndarray[n_edges]

Edge values.

required
threshold float

Mask threshold.

0.05

Returns:

Name Type Description
tuple (ndarray[n_unmasked, 2], ndarray[n_unmasked])

Unmasked edges and edge values.

orient_cycle(points, cycle_edges) staticmethod

Orients a given cycle so that the cycle normal points away from the origin.

Parameters:

Name Type Description Default
points ndarray[N, 3]

Coordinates of the graph.

required
cycle_edges ndarray[n_cycle_edges, 2]

Edges of the cycle.

required

Returns:

Type Description
ndarray

np.ndarray[n_cycle_edges, 2]: Oriented edges of the cycle.

run()

Applies the curl or gradient projection matrix of the input edge values X to yield the curl-free and gradient-free components X_G andX_C. Returns: tuple(np.ndarray[n_edges], np.ndarray[n_edges]): Curl-free and gradient-free component.

set_method(method)

Define the decomposition method, default: 'cut'

set_use_points(use_points=True)

ExtendedPhaseMapping

Pipeline for extended phase mapping on phasefield data.

This class processes a given phasefield by applying optional filters, extracting cycles (from faces and/or boundaries), and categorizing them into critical, noncritical, and wavefront cycles. It provides a structured way to analyze spatiotemporal phase dynamics using topological criteria.

Attributes:

Name Type Description
phasefield PhaseField

The input phasefield mesh.

phasefield_filters list

List of filters to apply to the phasefield.

cycles DataFrame

DataFrame containing all extracted cycles.

critical_cycles DataFrame

Cycles with non-zero topological charge.

noncritical_cycles DataFrame

Cycles with zero topological charge and more nodes than a single face.

wavefront_cycles DataFrame

Cycles corresponding to propagating wavefronts (non-zero wave number, zero topological charge, and equal to the face size).

critical_cycles = pd.DataFrame() instance-attribute

cycles = None instance-attribute

noncritical_cycles = pd.DataFrame() instance-attribute

phasefield = phasefield instance-attribute

phasefield_filters = phasefield_filters or [] instance-attribute

wavefront_cycles = pd.DataFrame() instance-attribute

__init__(phasefield, phasefield_filters=None)

Initialize the ExtendedPhaseMapping pipeline.

Parameters:

Name Type Description Default
phasefield PhaseField

The phasefield mesh to be processed.

required
phasefield_filters list

List of functions to filter the phasefield.

None

run(extract_faces=True, extract_boundaries=True)

Execute the ExtendedPhaseMapping pipeline.

Applies filters and extracts cycles from the phasefield.

Parameters:

Name Type Description Default
extract_faces bool

Whether to extract cycles from the faces of the phasefield (Default=True).

True
extract_boundaries bool

Whether to extract cycles from the boundaries of the phasefield (Default=True).

True

NKAlgorithm

Bases: Algorithm, ABC

Abstract base class for running networkit-based algorithms.

graph = graph.dgm_graph instance-attribute

nk_graph = graph.nk_graph instance-attribute

__init__(graph)

Pass either a preconfigured dgm.graph.NKGraph or a Networkit graph. Alternatively, you can pas a dgm.graph.Graph and a networkit graph will be created using a default template.

set_number_of_threads(number_of_threads)

Set number of threads used by Networkit.

Parameters:

Name Type Description Default
number_of_threads int

Number of threads.

required

to_nk_graph(graph)

NodeSources

Calculate normalized in/out flow balance and determine if each node is a source or a sink.

contained_flows = contained_flows instance-attribute

in_flows = in_flows instance-attribute

out_flows = out_flows instance-attribute

__init__(in_flows, out_flows, contained_flows)

run(min_edges=2)

Calculate normalized in/out flow balance and determine if each node is a source or a sink.

Source nodes are labeled as 1, sink nodes are labeled as -1. If the balance falls within the range [-threshold, threshold], the nodes are neither sources nor sinks and labeled as 0.

Returns:

Type Description
ndarray

np.ndarray: nodes heatmap of normalized in/out flow balance

PhaseMapping

Bases: Algorithm

Convert LATs or signals into phase values.

  • For signals, the Hilbert transform method is used.
  • For LATs, the sawtooth method is used.

method = method instance-attribute

observables = observables instance-attribute

time_axis = time_axis instance-attribute

__init__(observables, time_axis, method)

from_lats(lats, start=None, stop=None, dt=1.0) classmethod

Generate a sawtooth phase map from local activation times (LATs).

from_periodic_lat(initial_lats, period, num_of_period=3, start=None, stop=None, dt=1.0) classmethod

Construct a PhaseMapping by extrapolating a single LAT value periodically.

from_signals(signals, start=None, stop=None, dt=1.0) classmethod

Create phase values from signals using the Hilbert transform.

run()

Dispatch to the selected method.

VectorField

delta_lat = graph.edges.weights instance-attribute

distances = graph.edges.distances instance-attribute

edges = graph.edges.indices instance-attribute

normalized = False instance-attribute

points = graph.points instance-attribute

__init__(graph)

Creates VectorField object.

Parameters:

Name Type Description Default
graph Graph object

The graph for which to calculate the vector field.

required

calculate_weighted_vf(delta_lat)

Calculates the vector field in each node by taking a weighted average over all incoming and outgoing vectors for a node.

Parameters:

Name Type Description Default
delta_lat N dimensional array

The delta_lat on each vector. N has to be equal to the amount of vectors in the graph.

required

Returns:

Type Description
ndarray

VectorField in each node of the graph.

normalize(vectors) staticmethod

Normalizes M-dimensional vectors.

Parameters:

Name Type Description Default
vectors [N, M] dimensional array

The vectors to normalize.

required

Returns:

Type Description
ndarray

np.ndarray: The normalized vectors ([N, M] dimensional array).

normalized_avg()

Calculates the vector field in each node by taking the average over all normalized incoming and outgoing vectors of a node.

Returns:

Type Description
ndarray

np.ndarray: Vector field in each node of the graph.

set_normalized(normalized=True)

If set to True, the vector field is normalized.

weighted_avg_inverse_speed()

Calculates the vector field in each node by taking a weighted average over all incoming and outgoing vectors for a node. The weight on the vectors is the lat difference between the start and end point divided by the distance between start and end point (= inverse speed). This is the most stable vector field.

Returns:

Type Description
ndarray

np.ndarray: Vector field in each node of the graph.

weighted_avg_speed()

Calculates the vector field in each node by taking a weighted average over all incoming and outgoing vectors for a node. The weight on the vectors is the distance between start and end point divided by the lat difference between the start and end point (= speed).

Returns:

Type Description
ndarray

np.ndarray: Vector field in each node of the graph.