Utilities
Utility helpers for :mod:pyrecest.
anis = average_nis
module-attribute
mae = mean_absolute_error
module-attribute
mse = mean_squared_error
module-attribute
nees = normalized_estimation_error_squared
module-attribute
nis = normalized_innovation_squared
module-attribute
rmse = root_mean_squared_error
module-attribute
__all__ = ['MultiSessionAssignmentResult', 'solve_multisession_assignment', 'solve_multisession_assignment_from_similarity', 'solve_multisession_assignment_with_observation_costs', 'stitch_tracks_from_pairwise_scores', 'tracks_to_index_matrix', 'tracks_to_session_labels', 'anis', 'anees', 'chi_square_confidence_bounds', 'chi_square_confidence_interval', 'consistency_fraction', 'eot_shape_iou', 'extent_error', 'extent_intersection_over_union', 'extent_matrix_error', 'extent_wasserstein_distance', 'false_track_rate', 'gaussian_wasserstein_distance', 'gospa_distance', 'iou_polygon', 'is_chi_square_consistent', 'is_within_chi_square_confidence_interval', 'mae', 'missed_track_rate', 'mospa_distance', 'mse', 'nees', 'nees_confidence_bounds', 'nees_confidence_interval', 'nis', 'nis_confidence_bounds', 'nis_confidence_interval', 'ospa_distance', 'rmse', 'score_false_tracks', 'score_missed_tracks', 'score_track_latency', 'score_track_outcomes', 'score_track_purity', 'track_latencies', 'track_purity', 'CalibratedPairwiseAssociationModel', 'LogisticPairwiseAssociationModel', 'NamedPairwiseFeatureSchema', 'pairwise_feature_tensor', 'HistoryRecorder', 'ThinPlateSplineRegistrationResult', 'ThinPlateSplineTransform', 'estimate_thin_plate_spline', 'joint_tps_registration_assignment', 'murty_k_best_assignments', 'pairwise_covariance_shape_components', 'pairwise_mahalanobis_distances', 'complete_track_set', 'normalize_track_matrix', 'pairwise_track_set', 'reference_fragment_counts', 'score_complete_tracks', 'score_false_continuations', 'score_fragmentation', 'score_pairwise_tracks', 'score_track_fragmentation', 'score_track_links', 'score_track_matrices', 'summarize_track_errors', 'summarize_tracks', 'track_error_ledger', 'track_lengths', 'track_pair_set']
module-attribute
CalibratedPairwiseAssociationModel
dataclass
Association model wrapper that keeps a named pairwise feature schema.
The wrapped model may expose predict_match_probability,
predict_proba, or pairwise_cost_matrix. Component mappings are first
converted to tensors via schema before being passed to the model.
model
instance-attribute
schema
instance-attribute
probability_clip
instance-attribute
feature_names
property
Ordered feature names expected by the wrapped model.
__init__(model, feature_names=None, *, schema=None, transforms=None, probability_clip=1e-12)
build_feature_tensor(components)
Build a feature tensor using this model's schema.
predict_match_probability(features_or_components)
Return calibrated match probabilities for tensors or components.
pairwise_probability_matrix_from_components(components)
Convert components into calibrated pairwise probabilities.
pairwise_cost_matrix_from_components(components, *, mode='negative_log_probability')
Convert components into calibrated assignment costs.
pairwise_cost_matrix(features_or_components, *, mode='negative_log_probability')
Convert features or components into an assignment cost matrix.
NamedPairwiseFeatureSchema
dataclass
Named schema for building pairwise feature tensors from components.
Parameters
feature_names:
Ordered names of the feature planes to stack on the final tensor axis.
If no transform is registered for a name, the same key is looked up in
components when building a tensor.
transforms:
Optional mapping from feature name to a callable receiving the full
component mapping and returning the feature plane. This keeps derived
features domain-specific without baking their semantics into PyRecEst.
feature_names
instance-attribute
transforms
instance-attribute
__init__(feature_names, *, transforms=None)
__len__()
__iter__()
feature_index(feature_name)
Return the last-axis index of a named feature.
build_tensor(components)
Build a (..., n_features) tensor from named pairwise components.
LogisticPairwiseAssociationModel
Learn pairwise match probabilities from arbitrary association features.
The model uses binary logistic regression with optional feature standardization, L2 regularization, and support for severe class imbalance. It is intentionally dependency-light and implemented with NumPy only so that it can be used inside PyRecEst without adding a machine-learning stack.
Parameters
fit_intercept:
Whether to learn an intercept term.
l2_regularization:
Non-negative L2 regularization strength applied to the coefficients.
The intercept is not regularized.
max_iterations:
Maximum number of Newton / IRLS iterations.
tolerance:
Stop once the largest absolute parameter update falls below this value.
standardize:
Whether to z-score features before optimization.
class_weight:
None for unweighted fitting, "balanced" to automatically rebalance
positive and negative examples, or a dictionary containing weights for
labels 0 and 1.
probability_clip:
Numerical clipping applied to probabilities before taking logarithms.
Notes
The fit method accepts both a flattened feature matrix and a pairwise tensor. This makes it convenient to train directly from a ground-truth match matrix:
model = LogisticPairwiseAssociationModel(class_weight="balanced") model.fit(pairwise_features, match_labels) costs = model.pairwise_cost_matrix(pairwise_features)
Here pairwise_features may contain, for example, centroid distance,
overlap, and shape-correlation channels for every candidate neuron pair.
fit_intercept = fit_intercept
instance-attribute
l2_regularization = float(l2_regularization)
instance-attribute
max_iterations = int(max_iterations)
instance-attribute
tolerance = float(tolerance)
instance-attribute
standardize = bool(standardize)
instance-attribute
class_weight = class_weight
instance-attribute
probability_clip = float(probability_clip)
instance-attribute
n_features_in_ = None
instance-attribute
feature_mean_ = None
instance-attribute
feature_scale_ = None
instance-attribute
coefficients_ = None
instance-attribute
intercept_ = None
instance-attribute
n_iter_ = 0
instance-attribute
converged_ = False
instance-attribute
class_weights_ = None
instance-attribute
__init__(*, fit_intercept=True, l2_regularization=0.001, max_iterations=100, tolerance=1e-08, standardize=True, class_weight='balanced', probability_clip=1e-12)
fit(features, labels, sample_weight=None)
Fit the association model.
decision_function(features)
Return posterior log-odds for the provided feature vectors.
predict_log_odds(features)
Alias for :meth:decision_function.
predict_match_probability(features)
Return posterior match probabilities for the provided feature vectors.
predict(features, threshold=0.5)
Predict binary match decisions using the supplied threshold.
pairwise_cost_matrix(pairwise_features, *, mode='negative_log_probability')
Convert pairwise features into an assignment cost matrix.
HistoryRecorder
Record and retrieve named histories.
Histories come in two flavors:
- padded numeric histories, which are stored as a 2-D backend array and can grow in their first dimension over time while earlier columns are padded with NaNs, and
- generic histories, which are stored as Python lists of deep-copied values.
__init__()
register(name, initial_value=None, pad_with_nan=False)
Register a named history and return its storage object.
record(name, value, pad_with_nan=None, copy_value=True)
Append a value to the named history and return the updated history.
clear(name=None)
Clear a named history or all histories in place.
get(name, default=None)
Return the stored history for name.
items()
Iterate over (name, history) pairs.
keys()
Return the registered history names.
values()
Return the stored histories.
__contains__(name)
__getitem__(name)
__len__()
append_padded(curr_ests, estimates_over_time)
staticmethod
Append a column to a possibly growing 2-D history array.
MultiSessionAssignmentResult
dataclass
Result of :func:solve_multisession_assignment.
Attributes
tracks
One dictionary per recovered track. Keys are session indices and values
are detection indices within that session.
matched_edges
Directed edges selected by the optimizer as
((source_session, source_detection), (target_session, target_detection), adjusted_cost).
The reported edge cost already includes the configured gap penalty.
total_cost
Objective value of the globally optimal assignment, including track
start and end costs.
tracks
instance-attribute
matched_edges
instance-attribute
total_cost
instance-attribute
observation_to_track_index()
Return a mapping from observation to recovered track index.
to_session_labels(session_sizes=None, *, fill_value=-1)
Convert the recovered tracks to dense per-session label arrays.
Parameters
session_sizes Optional per-session detection counts. When omitted, sizes are inferred from the track content. fill_value Value used for unassigned detections.
__init__(tracks, matched_edges, total_cost)
ThinPlateSplineRegistrationResult
dataclass
Bases: RegistrationResultBase
Result of alternating TPS registration and assignment.
transform
instance-attribute
__init__(assignment, matched_reference_indices, matched_moving_indices, transformed_reference_points, matched_costs, rmse, n_iterations, converged, transform)
ThinPlateSplineTransform
dataclass
Two-dimensional thin-plate-spline transform.
Parameters
control_points:
Control points with shape (n_control, 2).
weights:
Non-rigid TPS weights with shape (n_control, 2).
affine_coefficients:
Affine coefficients with shape (3, 2) acting on
[1, x, y].
control_points
instance-attribute
weights
instance-attribute
affine_coefficients
instance-attribute
dim
property
Dimensionality of the transform domain.
__post_init__()
identity()
staticmethod
Return the identity 2D TPS transform.
from_translation(translation)
staticmethod
Return a TPS transform representing a pure translation.
apply(points)
Apply the transform to an (n_points, 2) array of points.
__init__(control_points, weights, affine_coefficients)
murty_k_best_assignments(cost_matrix, k=1, row_non_assignment_costs=None, col_non_assignment_costs=None)
Compute the k best one-to-one partial assignments.
Parameters
cost_matrix : array_like, shape (n_rows, n_cols)
Matrix containing the cost of assigning each row to each column.
Forbidden assignments can be encoded as numpy.inf.
k : int, default=1
Number of ranked assignments to return.
row_non_assignment_costs : array_like, optional
Cost incurred when a row remains unassigned. If omitted, zero cost is
used for all rows.
col_non_assignment_costs : array_like, optional
Cost incurred when a column remains unassigned. If omitted, zero cost is
used for all columns.
Returns
list[dict]
Ranked assignment solutions in ascending cost order. Each dictionary has
the keys assignment (matched column per row or -1),
unassigned_rows, unassigned_cols, and cost.
Notes
The implementation follows Murty's partitioning strategy on an augmented square assignment formulation. Branching is performed only over the original rows, which directly yields unique ranked partial assignments.
pairwise_feature_tensor(components, feature_names, transforms=None)
Build a pairwise feature tensor from named component planes.
All feature planes must have the same shape. Non-finite values are converted
to finite sentinels: nan -> 0, +inf -> 1e6, and -inf -> -1e6.
anees(estimates, uncertainties, groundtruths)
Backward-compatible alias for average NEES.
chi_square_confidence_bounds(degrees_of_freedom, *, n_samples=1, confidence=0.95)
Return two-sided chi-square bounds for an averaged NEES/NIS statistic.
chi_square_confidence_interval(degrees_of_freedom, *, n_samples=1, confidence=0.95)
Alias for :func:chi_square_confidence_bounds.
consistency_fraction(values, lower, upper)
Return the fraction of scalar values inside [lower, upper].
eot_shape_iou(shape1, shape2)
Return polygon IoU for extended-object shape estimates.
extent_error(estimated_extent, reference_extent, *, ord='fro', relative=False)
Alias for :func:extent_matrix_error.
extent_intersection_over_union(shape1, shape2)
Alias for polygon IoU used by extended-object tracking metrics.
extent_matrix_error(estimated_extent, reference_extent, *, ord='fro', relative=False)
Return matrix-norm error between estimated and reference extents.
extent_wasserstein_distance(estimated_extent, reference_extent, *, squared=False)
Return the covariance/extent part of the Gaussian 2-Wasserstein distance.
gaussian_wasserstein_distance(mean1, covariance1, mean2, covariance2, *, squared=False)
Return the 2-Wasserstein distance between Gaussian distributions.
gospa_distance(estimated_points, reference_points, *, cutoff, order=1.0, alpha=2.0, distance_fn=None, return_components=False)
Return the generalized OSPA distance between two finite sets.
iou_polygon(polygon1, polygon2)
Return intersection over union for two polygonal shapes.
is_chi_square_consistent(statistic, degrees_of_freedom, *, n_samples=1, confidence=0.95)
Return whether a scalar statistic lies inside chi-square bounds.
is_within_chi_square_confidence_interval(statistic, degrees_of_freedom, *, n_samples=1, confidence=0.95)
Alias for :func:is_chi_square_consistent.
mospa_distance(estimated_point_sets, reference_point_sets, *, cutoff, order=1.0, distance_fn=None, return_per_step=False)
Return mean OSPA over a sequence of finite-set estimates.
nees_confidence_bounds(state_dim, *, n_samples=1, confidence=0.95)
Return chi-square consistency bounds for NEES or ANEES.
nees_confidence_interval(state_dim, *, n_samples=1, confidence=0.95)
Alias for :func:nees_confidence_bounds.
nis_confidence_bounds(measurement_dim, *, n_samples=1, confidence=0.95)
Return chi-square consistency bounds for NIS or ANIS.
nis_confidence_interval(measurement_dim, *, n_samples=1, confidence=0.95)
Alias for :func:nis_confidence_bounds.
ospa_distance(estimated_points, reference_points, *, cutoff, order=1.0, distance_fn=None, return_components=False)
Return the optimal sub-pattern assignment distance between two finite sets.
solve_multisession_assignment(pairwise_costs, session_sizes=None, *, start_cost=0.0, end_cost=0.0, gap_penalty=0.0, cost_threshold=None)
Recover globally consistent tracks across multiple sessions.
Parameters
pairwise_costs
Either a mapping from (source_session, target_session) to a cost
matrix of shape (n_source, n_target), or a sequence of consecutive
session-to-session cost matrices. When a sequence is supplied, matrix
k is interpreted as the cost matrix for session k to session
k + 1.
session_sizes
Optional per-session detection counts. This is only required when some
sessions have no pairwise cost matrix, or when isolated singleton
detections should still be represented in the result. A sequence is
interpreted as counts for sessions 0, 1, ..., S-1.
start_cost
Penalty for starting a new track.
end_cost
Penalty for ending a track.
gap_penalty
Additional penalty applied per skipped session for non-consecutive
edges. This penalty is added on top of the supplied edge cost.
cost_threshold
Optional upper bound for admissible link costs after gap penalties are
applied. Edges with larger costs are forbidden.
Returns
MultiSessionAssignmentResult Globally optimal tracks and the selected directed edges.
Notes
Let N be the total number of observations. If every observation starts
as a singleton track, the baseline cost is
N * (start_cost + end_cost).
Adding an admissible edge with adjusted cost c merges two track ends and
therefore changes the objective by c - start_cost - end_cost. The
implementation maximizes the total gain
start_cost + end_cost - c
subject to at-most-one-predecessor and at-most-one-successor constraints. This is equivalent to the minimum-cost path-cover objective. Internally, the sparse matching problem is reduced to a rectangular assignment in which every source observation can either connect to an admissible successor or to its own dummy "unmatched" column.
tracks_to_session_labels(tracks, session_sizes=None, *, fill_value=-1)
Convert explicit tracks to dense per-session label arrays.
Parameters
tracks
Sequence of track representations. Each track can either be a mapping
from session index to detection index or a sequence of
(session_index, detection_index) pairs.
session_sizes
Optional per-session detection counts. When omitted, sizes are inferred
from the maximum detection index present in each session. Missing
sessions are represented by empty arrays.
fill_value
Value used for detections that are not assigned to any track.
Returns
tuple One integer array per session, indexed by session number.
solve_multisession_assignment_with_observation_costs(pairwise_costs, session_sizes=None, *, start_cost=0.0, end_cost=0.0, start_costs=None, end_costs=None, gap_penalty=0.0, cost_threshold=None)
Solve multi-session assignment with per-observation start/end costs.
solve_multisession_assignment_from_similarity(pairwise_scores, session_sizes=None, *, min_score=None, max_gap=None, gap_penalty=0.0, start_cost=0.0, end_cost=0.0, score_to_cost=None)
Score-native wrapper around :func:solve_multisession_assignment.
stitch_tracks_from_pairwise_scores(pairwise_scores, session_sizes=None, **kwargs)
Track2p-style alias for the score-native wrapper.
tracks_to_index_matrix(tracks, session_sizes=None, *, fill_value=-1)
Convert tracks to a dense track x session ROI-index matrix.
estimate_thin_plate_spline(source_points, target_points, *, regularization=0.001)
Estimate a thin-plate-spline transform from matched 2D point pairs.
Parameters
source_points, target_points:
Arrays of shape (n_points, 2) describing matched point pairs.
regularization:
Non-negative ridge penalty applied to the TPS kernel matrix.
joint_tps_registration_assignment(reference_points, moving_points, *, initial_transform=None, max_cost=float('inf'), cost_function=None, max_iterations=25, tolerance=1e-06, min_matches=3, regularization=0.001)
Alternating thin-plate-spline registration and one-to-one assignment.
This function alternates between: 1. assigning transformed reference points to moving points using the Hungarian algorithm with optional gating; and 2. refitting a smooth thin-plate-spline warp from the current matches.
Parameters
reference_points:
Landmark locations from the reference session, shape (n_ref, 2).
moving_points:
Landmark locations from the moving/current session, shape (n_moving, 2).
initial_transform:
Optional starting transform. If omitted, the transform is initialized
with a robust median-based translation.
max_cost:
Optional gating threshold on the association cost.
cost_function:
Optional callable receiving transformed reference points and moving
points and returning a cost matrix of shape (n_ref, n_moving).
This allows centroid costs, ROI overlap costs, or morphology-aware
hybrid costs to be plugged into the registration loop.
max_iterations:
Maximum number of alternating assignment/refit iterations.
tolerance:
Convergence threshold on the change of the transformed reference point set.
min_matches:
Minimum number of matched pairs required before refitting the TPS warp.
regularization:
Non-negative ridge penalty for TPS fitting.
pairwise_covariance_shape_components(covariances_a, covariances_b, *, epsilon=1e-06)
Return pairwise covariance shape, scale, and similarity components.
The covariance-shape cost compares trace-normalized covariance matrices with
a Frobenius norm. This makes the feature sensitive to orientation and
anisotropy while ignoring overall scale. The log-determinant cost measures
scale mismatch separately. The shape similarity is exp(-shape_cost).
Parameters
covariances_a, covariances_b:
Covariance stacks with shape (dim, dim, n_items).
epsilon:
Strictly positive floor used for traces and determinants.
Returns
shape_cost, logdet_cost, shape_similarity:
Three matrices with shape (n_a, n_b).
pairwise_mahalanobis_distances(means_a, covariances_a, means_b, covariances_b, *, regularization=0.0)
Return covariance-normalized distances between two Gaussian stacks.
For a pair of items i and j, the returned value is
sqrt((mu_i - nu_j)^T (Sigma_i + Lambda_j + regularization * I)^+ (mu_i - nu_j)),
where ^+ denotes the Moore-Penrose pseudoinverse. Using the summed
covariance makes the feature symmetric in the two uncertain estimates and is
the standard normalization for comparing two independent Gaussian position
estimates.
Parameters
means_a, means_b:
Mean stacks with shape (dim, n_items).
covariances_a, covariances_b:
Covariance stacks with shape (dim, dim, n_items). The number of
covariance matrices must match the corresponding number of means.
regularization:
Optional non-negative diagonal loading added to every summed covariance
before inversion.
Returns
array-like
Matrix with shape (n_a, n_b).
complete_track_set(track_matrix, *, session_indices=None)
Return exact full-track tuples present in every selected session.
normalize_track_matrix(track_matrix)
Return an object matrix containing integer observation indices or None.
pairwise_track_set(track_matrix, *, session_pairs=None)
Backward-compatible alias for :func:track_pair_set.
reference_fragment_counts(predicted_track_matrix, reference_track_matrix)
Return the number of predicted fragments covering each reference track.
score_complete_tracks(predicted_track_matrix, reference_track_matrix, *, session_indices=None)
Score exact complete-track recovery with precision, recall, and F1.
score_false_continuations(predicted_track_matrix, reference_track_matrix, *, session_pairs=None)
Score predicted forward links that contradict the reference identity map.
score_fragmentation(predicted_track_matrix, reference_track_matrix)
Backward-compatible alias for :func:score_track_fragmentation.
score_pairwise_tracks(predicted_track_matrix, reference_track_matrix, *, session_pairs=None)
Score pairwise links using BayesCaTrack-compatible metric names.
score_track_fragmentation(predicted_track_matrix, reference_track_matrix)
Score fragmentation of reference identities across predicted tracks.
score_track_links(predicted_track_matrix, reference_track_matrix, *, session_pairs=None)
Score pairwise links induced by predicted and reference track matrices.
score_track_matrices(predicted_track_matrix, reference_track_matrix, *, session_pairs=None, complete_session_indices=None)
Return aggregate link, complete-track, fragmentation, and ledger metrics.
summarize_track_errors(predicted_track_matrix, reference_track_matrix, *, session_pairs=None)
Return aggregate track-level error metrics.
summarize_tracks(track_matrix)
Summarize the number and length of tracks.
track_error_ledger(predicted_track_matrix, reference_track_matrix, *, session_pairs=None)
Return detailed track-, link-, and duplicate-observation error ledgers.
track_lengths(track_matrix)
Return the number of present observations in each track row.
track_pair_set(track_matrix, *, session_pairs=None)
Return pairwise track links as (session_a, session_b, obs_a, obs_b).
false_track_rate(predicted_track_matrix, reference_track_matrix, *, min_length=1)
Return the fraction of evaluated predicted tracks that are false.
missed_track_rate(predicted_track_matrix, reference_track_matrix, *, min_length=1)
Return the fraction of evaluated reference tracks that are missed.
score_false_tracks(predicted_track_matrix, reference_track_matrix, *, min_length=1)
Return metrics for predicted tracks that contain no reference observation.
score_missed_tracks(predicted_track_matrix, reference_track_matrix, *, min_length=1)
Return metrics for reference tracks with no predicted observation support.
score_track_latency(predicted_track_matrix, reference_track_matrix, *, session_times=None)
Return aggregate first-detection latency metrics.
score_track_outcomes(predicted_track_matrix, reference_track_matrix, *, session_times=None)
Return fragmentation, purity, false-track, missed-track, and latency metrics.
score_track_purity(predicted_track_matrix, reference_track_matrix)
Return predicted-track identity purity metrics.
A predicted track's purity is the fraction of its observations that belong
to its dominant reference identity. Observations absent from the reference
matrix count as impure in mean_track_purity and
observation_weighted_track_purity.
track_latencies(predicted_track_matrix, reference_track_matrix, *, session_times=None, missed_value=np.nan)
Return first-detection latency for each non-empty reference track.
track_purity(predicted_track_matrix, reference_track_matrix)
Return observation-weighted predicted-track purity.