API Reference
Core API
The core components of PyEHM are the EHM
and EHM2
classes, that constitute implementations of the
EHM [EHM1] and EHM2 [EHM2] algorithms for data association.
The interfaces of these classes are documented below.
- class pyehm.core.EHM[source]
Efficient Hypothesis Management (EHM)
An implementation of the EHM algorithm, as documented in [EHM1].
- static construct_net(validation_matrix)[source]
Construct the EHM net as per Section 3.1 of [EHM1]
- Parameters:
validation_matrix (
numpy.ndarray
) – An indicator matrix of shape (num_tracks, num_detections + 1) indicating the possible (aka. valid) associations between tracks and detections. The first column corresponds to the null hypothesis (hence contains all ones).- Returns:
The constructed net object
- Return type:
- static compute_association_probabilities(net, likelihood_matrix)[source]
Compute the joint association weights, as described in Section 3.3 of [EHM1]
- Parameters:
net (
EHMNet
) – A net object representing the valid joint association hypotheseslikelihood_matrix (
numpy.ndarray
) – A matrix of shape (num_tracks, num_detections + 1) containing the unnormalised likelihoods for all combinations of tracks and detections. The first column corresponds to the null hypothesis.
- Returns:
A matrix of shape (num_tracks, num_detections + 1) containing the normalised association probabilities for all combinations of tracks and detecrtons. The first column corresponds to the null hypothesis.
- Return type:
- classmethod run(validation_matrix, likelihood_matrix)[source]
Run EHM to compute and return association probabilities
- Parameters:
validation_matrix (
numpy.ndarray
) – An indicator matrix of shape (num_tracks, num_detections + 1) indicating the possible (aka. valid) associations between tracks and detections. The first column corresponds to the null hypothesis (hence contains all ones).likelihood_matrix (
numpy.ndarray
) – A matrix of shape (num_tracks, num_detections + 1) containing the unnormalised likelihoods for all combinations of tracks and detections. The first column corresponds to the null hypothesis.
- Returns:
A matrix of shape (num_tracks, num_detections + 1) containing the normalised association probabilities for all combinations of tracks and detections. The first column corresponds to the null hypothesis.
- Return type:
- class pyehm.core.EHM2[source]
Bases:
EHM
Efficient Hypothesis Management 2 (EHM2)
An implementation of the EHM2 algorithm, as documented in [EHM2].
- classmethod construct_net(validation_matrix)[source]
Construct the EHM net as per Section 4 of [EHM2]
- Parameters:
validation_matrix (
numpy.ndarray
) – An indicator matrix of shape (num_tracks, num_detections + 1) indicating the possible (aka. valid) associations between tracks and detections. The first column corresponds to the null hypothesis (hence contains all ones).- Returns:
The constructed net object
- Return type:
- Raises:
ValueError – If the provided
validation_matrix
is such that tracks can be divided into separate clusters. See the Note below for work-around.
Note
If the provided
validation_matrix
is such that tracks can be divided into separate clusters, this method will raise a ValueError exception. To work-around this issue, you can use thegen_clusters()
function to first generate individual clusters and then generate a net for each cluster, as shown below:from pyehm.core import EHM2 from pyehm.utils import gen_clusters validation_matrix = <Your validation matrix> clusters, _ = gen_clusters(validation_matrix) nets = [] for cluster in clusters: nets.append(EHM2.construct_net(cluster.validation_matrix)
- static construct_tree(validation_matrix)[source]
Construct the EHM2 tree as per section 4.3 of [EHM2]
- Parameters:
validation_matrix (
numpy.ndarray
) – An indicator matrix of shape (num_tracks, num_detections + 1) indicating the possible (aka. valid) associations between tracks and detections. The first column corresponds to the null hypothesis (hence contains all ones).- Returns:
The constructed tree object
- Return type:
- Raises:
ValueError – If the provided
validation_matrix
is such that tracks can be divided into separate clusters. See the Note below for work-around.
Note
If the provided
validation_matrix
is such that tracks can be divided into separate clusters, this method will raise a ValueError exception. To work-around this issue, you can use thegen_clusters()
function to first generate individual clusters and then generate a tree for each cluster, as shown below:from pyehm.core import EHM2 from pyehm.utils import gen_clusters validation_matrix = <Your validation matrix> clusters, _ = gen_clusters(validation_matrix) trees = [] for cluster in clusters: trees.append(EHM2.construct_tree(cluster.validation_matrix)
- static compute_association_probabilities(net, likelihood_matrix)[source]
Compute the joint association weights, as described in Section 4.2 of [EHM2]
- Parameters:
net (
EHMNet
) – A net object representing the valid joint association hypotheseslikelihood_matrix (
numpy.ndarray
) – A matrix of shape (num_tracks, num_detections + 1) containing the unnormalised likelihoods for all combinations of tracks and detections. The first column corresponds to the null hypothesis.
- Returns:
A matrix of shape (num_tracks, num_detections + 1) containing the normalised association probabilities for all combinations of tracks and detecrtons. The first column corresponds to the null hypothesis.
- Return type:
- classmethod run(validation_matrix, likelihood_matrix)
Run EHM to compute and return association probabilities
- Parameters:
validation_matrix (
numpy.ndarray
) – An indicator matrix of shape (num_tracks, num_detections + 1) indicating the possible (aka. valid) associations between tracks and detections. The first column corresponds to the null hypothesis (hence contains all ones).likelihood_matrix (
numpy.ndarray
) – A matrix of shape (num_tracks, num_detections + 1) containing the unnormalised likelihoods for all combinations of tracks and detections. The first column corresponds to the null hypothesis.
- Returns:
A matrix of shape (num_tracks, num_detections + 1) containing the normalised association probabilities for all combinations of tracks and detections. The first column corresponds to the null hypothesis.
- Return type:
Utils API
The pyehm.utils
module contains helper classes and functions used by pyehm.core
.
- class pyehm.utils.EHMNetNode(layer, identity=None)[source]
A node in the
EHMNet
constructed byEHM
.- Parameters:
layer (
int
) – Index of the network layer in which the node is placed. Since a different layer in the network is built for each track, this also represented the index of the track this node relates to.identity (
set
ofint
) – The identity of the node. As per Section 3.1 of [EHM1], “the identity for each node is an indication of how measurement assignments made for tracks already considered affect assignments for tracks remaining to be considered”.
- class pyehm.utils.EHM2NetNode(layer, track=None, subnet=0, identity=None)[source]
Bases:
EHMNetNode
A node in the
EHMNet
constructed byEHM2
.- Parameters:
layer (
int
) – Index of the network layer in which the node is placed.track (
int
) – Index of track this node relates to.subnet (
int
) – Index of subnet to which the node belongs.identity (
set
ofint
) – The identity of the node. As per Section 3.1 of [EHM1], “the identity for each node is an indication of how measurement assignments made for tracks already considered affect assignments for tracks remaining to be considered”.
- class pyehm.utils.EHMNet(nodes, validation_matrix, edges=None)[source]
Represents the nets constructed by
EHM
andEHM2
.- Parameters:
nodes (
list
ofEHMNetNode
orEHM2NetNode
) – The nodes comprising the net.validation_matrix (
numpy.ndarray
) – An indicator matrix of shape (num_tracks, num_detections + 1) indicating the possible (aka. valid) associations between tracks and detections. The first column corresponds to the null hypothesis (hence contains all ones).edges (
dict
) – A dictionary that represents the edges between nodes in the network. The dictionary keys are tuples of the form`(parent, child)`
, where`parent`
and`child`
are the source and target nodes respectively. The values of the dictionary are the measurement indices that describe the parent-child relationship.
- property root: EHMNetNode | EHM2NetNode
The root node of the net.
- property nodes: List[EHMNetNode] | List[EHM2NetNode]
The nodes comprising the net
- property nodes_forward: Sequence[EHMNetNode] | Sequence[EHM2NetNode]
The net nodes, ordered by increasing layer
- add_node(node: EHMNetNode | EHM2NetNode, parent: EHMNetNode | EHM2NetNode, detection: int)[source]
Add a new node in the network.
- Parameters:
node (
EHMNetNode
orEHM2NetNode
) – The node to be added.parent (
EHMNetNode
orEHM2NetNode
) – The parent of the node.detection (
int
) – Index of measurement representing the parent child relationship.
- add_edge(parent: EHMNetNode | EHM2NetNode, child: EHMNetNode | EHM2NetNode, detection: int)[source]
Add edge between two nodes, or update an already existing edge by adding the detection to it.
- Parameters:
parent (
EHMNetNode
orEHM2NetNode
) – The parent node, i.e. the source of the edge.child (
EHMNetNode
orEHM2NetNode
) – The child node, i.e. the target of the edge.detection (
int
) – Index of measurement representing the parent child relationship.
- get_parents(node: EHMNetNode | EHM2NetNode) Sequence[EHMNetNode] | Sequence[EHM2NetNode] [source]
Get the parents of a node.
- Parameters:
node (
EHMNetNode
orEHM2NetNode
) – The node whose parents should be returned- Returns:
List of parent nodes
- Return type:
list
ofEHMNetNode
orEHM2NetNode
- get_children(node: EHMNetNode | EHM2NetNode) Sequence[EHMNetNode] | Sequence[EHM2NetNode] [source]
Get the children of a node.
- Parameters:
node (
EHMNetNode
orEHM2NetNode
) – The node whose children should be returned- Returns:
List of child nodes
- Return type:
list
ofEHMNetNode
orEHM2NetNode
- plot(ax: Axes = None, annotate=True)[source]
Plot the net.
- Parameters:
ax (
matplotlib.axes.Axes
) – Axes on which to plot the netannotate (
bool
) – Flag that dictates whether or not to draw node and edge labels on the plotted net. The default isTrue
- class pyehm.utils.EHM2Tree(track, children, detections, subtree)[source]
Represents the track tree structure generated by
construct_tree()
.The
EHM2Tree
object represents both a tree as well as the root node in the tree.- Parameters:
- plot(ax: Axes = None)[source]
Plot the tree.
- Parameters:
ax (
matplotlib.axes.Axes
) – Axes on which to plot the tree
- class pyehm.utils.Cluster(tracks=None, detections=None, validation_matrix=None, likelihood_matrix=None)[source]
A cluster of tracks sharing common detections.
- Parameters:
tracks (
list
of int) – Indices of tracks in clusterdetections (
list
of int) – Indices of detections in clustervalidation_matrix (
numpy.ndarray
) – The validation matrix for tracks and detections in the clusterlikelihood_matrix (
numpy.ndarray
) – The likelihood matrix for tracks and detections in the cluster
- pyehm.utils.gen_clusters(validation_matrix, likelihood_matrix=None)[source]
Cluster tracks into groups sharing detections
- Parameters:
validation_matrix (
numpy.ndarray
) – An indicator matrix of shape (num_tracks, num_detections + 1) indicating the possible (aka. valid) associations between tracks and detections. The first column corresponds to the null hypothesis (hence contains all ones).likelihood_matrix (
numpy.ndarray
) – A matrix of shape (num_tracks, num_detections + 1) containing the unnormalised likelihoods for all combinations of tracks and detections. The first column corresponds to the null hypothesis. The default is None, in which case the likelihood matrices of the generated clusters will also be None.
- Returns:
Plugins
Stone Soup
- class pyehm.plugins.stonesoup.JPDAWithEHM(hypothesiser: PDAHypothesiser)[source]
Bases:
JPDA
Joint Probabilistic Data Association with Efficient Hypothesis Management (EHM)
This is a faster alternative of the standard
JPDA
algorithm, which makes use of Efficient Hypothesis Management (EHM) to efficiently compute the joint associations. See Maskell et al. (2004) [EHM1] for more details.- associate(tracks, detections, timestamp, **kwargs)[source]
Associate tracks and detections
- Parameters:
tracks (set of
stonesoup.types.track.Track
) – Tracks which detections will be associated to.detections (set of
stonesoup.types.detection.Detection
) – Detections to be associated to tracks.timestamp (
datetime.datetime
) – Timestamp to be used for missed detections and to predict to.
- Returns:
Mapping of track to Hypothesis
- Return type:
mapping of
stonesoup.types.track.Track
:stonesoup.types.hypothesis.Hypothesis
- class pyehm.plugins.stonesoup.JPDAWithEHM2(hypothesiser: PDAHypothesiser)[source]
Bases:
JPDAWithEHM
Joint Probabilistic Data Association with Efficient Hypothesis Management 2 (EHM2)
This is an enhanced version of the
JPDAWithEHM
algorithm, that makes use of the Efficient Hypothesis Management 2 (EHM2) algorithm to efficiently compute the joint associations. See Horridge et al. (2006) [EHM2] for more details.- associate(tracks, detections, timestamp, **kwargs)
Associate tracks and detections
- Parameters:
tracks (set of
stonesoup.types.track.Track
) – Tracks which detections will be associated to.detections (set of
stonesoup.types.detection.Detection
) – Detections to be associated to tracks.timestamp (
datetime.datetime
) – Timestamp to be used for missed detections and to predict to.
- Returns:
Mapping of track to Hypothesis
- Return type:
mapping of
stonesoup.types.track.Track
:stonesoup.types.hypothesis.Hypothesis