From b3a35012cccc8dd1e67889f2434c3dfeddbf1df8 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Tue, 1 Oct 2024 16:20:43 +0100 Subject: [PATCH 1/3] Make passing measurements in distance hypothesiser optional --- stonesoup/hypothesiser/distance.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/stonesoup/hypothesiser/distance.py b/stonesoup/hypothesiser/distance.py index f9c30f77e..a1d7166a6 100644 --- a/stonesoup/hypothesiser/distance.py +++ b/stonesoup/hypothesiser/distance.py @@ -26,6 +26,10 @@ class DistanceHypothesiser(Hypothesiser): include_all: bool = Property( default=False, doc="If `True`, hypotheses beyond missed distance will be returned. Default `False`") + predict_with_measurements: bool = Property( + default=False, + doc="Whether to pass measurement/detection to the predictor. Default `False`" + ) def hypothesise(self, track, detections, timestamp, **kwargs): """ Evaluate and return all track association hypotheses. @@ -68,8 +72,12 @@ def hypothesise(self, track, detections, timestamp, **kwargs): for detection in detections: # Re-evaluate prediction - prediction = self.predictor.predict( - track, timestamp=detection.timestamp, measurement=detection, **kwargs) + if self.predict_with_measurements: + prediction = self.predictor.predict( + track, timestamp=detection.timestamp, measurement=detection, **kwargs) + else: + prediction = self.predictor.predict( + track, timestamp=detection.timestamp, **kwargs) # Compute measurement prediction and distance measure measurement_prediction = self.updater.predict_measurement( From 5f5d627d0dfa4fc5ff6d1ba6b412367eba56745f Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Wed, 2 Oct 2024 08:27:15 +0100 Subject: [PATCH 2/3] Minor doc string fixes for proposals --- stonesoup/proposal/base.py | 2 ++ stonesoup/proposal/simple.py | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/stonesoup/proposal/base.py b/stonesoup/proposal/base.py index 42379e469..118d6d8a5 100644 --- a/stonesoup/proposal/base.py +++ b/stonesoup/proposal/base.py @@ -7,7 +7,9 @@ class Proposal(Base): @abstractmethod def rvs(self, *args, **kwargs): r"""Proposal noise/sample generation function + Generates samples from the proposal. + Parameters ---------- state: :class:`~.State` diff --git a/stonesoup/proposal/simple.py b/stonesoup/proposal/simple.py index 0162711d9..a038bea04 100644 --- a/stonesoup/proposal/simple.py +++ b/stonesoup/proposal/simple.py @@ -27,14 +27,21 @@ class PriorAsProposal(Proposal): def rvs(self, prior: State, measurement=None, time_interval=None, **kwargs) -> Union[StateVector, StateVectors]: """Generate samples from the proposal. + Parameters ---------- state: :class:`~.State` The state to generate samples from. + measurement: :class:`~.Detection` + the measurement that will preferably used to get time interval + if provided(the default is `None`) + time_interval: :class:`datetime.time_delta` + time interval of the prediction is needed to propagate the states + Returns ------- - : :class:`~.ParticlePrediction` with samples drawn from the updated proposal - + : :class:`~.ParticlePrediction` + State with samples drawn from the updated proposal """ if measurement is not None: @@ -55,7 +62,7 @@ def rvs(self, prior: State, measurement=None, time_interval=None, class KFasProposal(Proposal): - """This proposal uses the kalman filter prediction and update steps to + """This proposal uses the Kalman filter prediction and update steps to generate new set of particles and weights """ predictor: Predictor = Property( @@ -66,13 +73,15 @@ class KFasProposal(Proposal): def rvs(self, prior: State, measurement: Detection = None, time_interval=None, **kwargs): """Generate samples from the proposal. - Use the kalman filter predictor and updater to create a new distribution + + Use the Kalman filter predictor and updater to create a new distribution + Parameters ---------- state: :class:`~.State` The state to generate samples from. measurement: :class:`~.Detection` - the measurement that is used in the update step of the kalman prediction, + the measurement that is used in the update step of the Kalman prediction, (the default is `None`) time_interval: :class:`datetime.time_delta` time interval of the prediction is needed to propagate the states @@ -80,6 +89,7 @@ def rvs(self, prior: State, measurement: Detection = None, time_interval=None, Returns ------- : :class:`~.ParticlePrediction` + State with samples drawn from the updated proposal """ if measurement is not None: From fc2adb236d5a541f74c94672de8a307238d82d78 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Wed, 2 Oct 2024 09:20:56 +0100 Subject: [PATCH 3/3] Add test for predict with measurements for DistanceHypothesiser --- stonesoup/hypothesiser/tests/test_distance.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/stonesoup/hypothesiser/tests/test_distance.py b/stonesoup/hypothesiser/tests/test_distance.py index 35535b22a..1989bbb16 100644 --- a/stonesoup/hypothesiser/tests/test_distance.py +++ b/stonesoup/hypothesiser/tests/test_distance.py @@ -2,6 +2,7 @@ import datetime import numpy as np +import pytest from ..distance import DistanceHypothesiser from ...types.detection import Detection @@ -10,7 +11,8 @@ from ... import measures -def test_mahalanobis(predictor, updater): +@pytest.mark.parametrize('predict_with_measurements', [True, False]) +def test_mahalanobis(predictor, updater, predict_with_measurements): timestamp = datetime.datetime.now() track = Track([GaussianState(np.array([[0]]), np.array([[1]]), timestamp)]) @@ -21,7 +23,8 @@ def test_mahalanobis(predictor, updater): measure = measures.Mahalanobis() hypothesiser = DistanceHypothesiser( - predictor, updater, measure=measure, missed_distance=3) + predictor, updater, measure=measure, missed_distance=3, + predict_with_measurements=predict_with_measurements) hypotheses = hypothesiser.hypothesise(track, detections, timestamp)