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