-
Notifications
You must be signed in to change notification settings - Fork 124
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #200 from dstl/Multi_Deleter
Added multi-deleter methods
- Loading branch information
Showing
3 changed files
with
160 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# -*- coding: utf-8 -*- | ||
"""Contains deleters which use a composite of deleters to decide whether a track is to be deleted | ||
""" | ||
|
||
from ..base import Property | ||
from .base import Deleter | ||
|
||
|
||
class CompositeDeleter(Deleter): | ||
""" Track deleter composed of multiple deleters. | ||
If :attr:`intersect` is True, deletes tracks if they satisfy the deletion conditions of each | ||
deleter listed in :attr:`deleters`. Otherwise deletes tracks if they satisfy the conditions of | ||
at least one deleter listed. | ||
""" | ||
|
||
deleters = Property([Deleter], doc="List of deleters to be applied to the track") | ||
intersect = Property( | ||
bool, default=True, | ||
doc="Boolean that determines whether the composite deleter will intersect or unify " | ||
"deletion results. Default is `True`, applying an intersection.") | ||
|
||
def check_for_deletion(self, track, **kwargs): | ||
"""Check if a given track should be deleted. | ||
Parameters | ||
---------- | ||
track : :class:`stonesoup.types.Track` | ||
A track object to be checked for deletion. | ||
Returns | ||
------- | ||
: :class:`bool` | ||
`True` if track should be deleted, `False` otherwise. | ||
""" | ||
if self.intersect: | ||
for deleter in self.deleters: | ||
if not deleter.check_for_deletion(track, **kwargs): | ||
return False | ||
return True | ||
else: | ||
for deleter in self.deleters: | ||
if deleter.check_for_deletion(track, **kwargs): | ||
return True | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
# -*- coding: utf-8 -*- | ||
import datetime | ||
|
||
import numpy as np | ||
import pytest | ||
|
||
from ..error import CovarianceBasedDeleter | ||
from ..multi import CompositeDeleter | ||
from ..time import UpdateTimeDeleter | ||
from ...types.detection import Detection | ||
from ...types.hypothesis import SingleHypothesis | ||
from ...types.state import GaussianState | ||
from ...types.track import Track | ||
from ...types.update import GaussianStateUpdate | ||
|
||
|
||
@pytest.fixture(params=[True, False]) | ||
def intersect(request): | ||
return request.param | ||
|
||
|
||
def test_multi_deleter_single(intersect): | ||
"""Test multi deleter classes with a single deleter""" | ||
|
||
# Create covariance based deleter | ||
timestamp = datetime.datetime.now() | ||
state = GaussianState( | ||
np.array([[0], [0]]), | ||
np.array([[100, 0], [0, 1]]), timestamp) | ||
track = Track() | ||
track.append(state) | ||
tracks = {track} | ||
state = GaussianState( | ||
np.array([[0], [0]]), | ||
np.array([[1, 0], [0, 1]]), timestamp) | ||
track = Track() | ||
track.append(state) | ||
tracks.add(track) | ||
cover_deletion_thresh = 100 | ||
deleter = CovarianceBasedDeleter(cover_deletion_thresh) | ||
|
||
# Test intersect deleter | ||
multi_deleter = CompositeDeleter([deleter], intersect) | ||
deleted_tracks = multi_deleter.delete_tracks(tracks) | ||
tracks -= deleted_tracks | ||
|
||
assert (len(tracks) == 1) | ||
assert (len(deleted_tracks) == 1) | ||
|
||
|
||
def test_multi_deleter_multiple(intersect): | ||
"""Test multi deleter classes with multiple deleters""" | ||
|
||
cover_deletion_thresh = 99 | ||
deleter = CovarianceBasedDeleter(cover_deletion_thresh) | ||
deleter2 = UpdateTimeDeleter(datetime.timedelta(minutes=10)) | ||
multi_deleter = CompositeDeleter([deleter, deleter2], intersect) | ||
|
||
# Create track that is not deleted by either deleter | ||
track = Track([ | ||
GaussianState( | ||
np.array([[0]]), | ||
np.array([[10]]), | ||
timestamp=datetime.datetime(2018, 1, 1, 10)), | ||
GaussianStateUpdate( | ||
[[0]], | ||
np.array([[10]]), | ||
SingleHypothesis(None, Detection([[0]])), | ||
timestamp=datetime.datetime(2018, 1, 1, 14)) | ||
]) | ||
tracks = {track} | ||
deleted_tracks = multi_deleter.delete_tracks(tracks) | ||
tracks -= deleted_tracks | ||
|
||
assert (len(tracks) == 1) | ||
assert (len(deleted_tracks) == 0) | ||
|
||
# Create track that is deleted by cbd but not time deleter | ||
track = Track([ | ||
GaussianState( | ||
np.array([[0]]), | ||
np.array([[100]]), | ||
timestamp=datetime.datetime(2018, 1, 1, 10)), | ||
GaussianStateUpdate( | ||
[[0]], | ||
np.array([[100]]), | ||
SingleHypothesis(None, Detection([[0]])), | ||
timestamp=datetime.datetime(2018, 1, 1, 14)) | ||
]) | ||
tracks = {track} | ||
|
||
deleted_tracks = multi_deleter.delete_tracks(tracks) | ||
tracks -= deleted_tracks | ||
|
||
if intersect: | ||
assert len(tracks) == 1 | ||
assert len(deleted_tracks) == 0 | ||
else: | ||
assert len(tracks) == 0 | ||
assert len(deleted_tracks) == 1 | ||
|
||
# Create track that is deleted by both cbd and time deleter | ||
tracks = {track} | ||
new_time = datetime.datetime(2018, 1, 1, 14, 25) | ||
deleted_tracks = multi_deleter.delete_tracks(tracks, timestamp=new_time) | ||
tracks -= deleted_tracks | ||
|
||
assert (len(tracks) == 0) | ||
assert (len(deleted_tracks) == 1) |