From 077d11da313c57ea74e984eb627de38aad0777d7 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Wed, 12 Oct 2022 13:59:30 +0100 Subject: [PATCH] Maintain order of truths in tutorials for reproducibility Due to simulating detections in tutorials, the order of the truths, will change which random noise sample goes with each detections, centred on the truth. Maintaining order of truths should ensure that same random sample is used consistently. Fixes #718 --- .../06_DataAssociation-MultiTargetTutorial.py | 5 ++- docs/tutorials/08_JPDATutorial.py | 3 +- docs/tutorials/09_Initiators_&_Deleters.py | 3 +- docs/tutorials/filters/GMPHDTutorial.py | 3 +- .../01_SingleSensorManagement.py | 38 ++++++---------- .../02_MultiSensorManagement.py | 34 ++++++-------- .../03_OptimisedSensorManagement.py | 45 ++++++++----------- 7 files changed, 55 insertions(+), 76 deletions(-) diff --git a/docs/tutorials/06_DataAssociation-MultiTargetTutorial.py b/docs/tutorials/06_DataAssociation-MultiTargetTutorial.py index b4813fc72..8e7aa0a1e 100644 --- a/docs/tutorials/06_DataAssociation-MultiTargetTutorial.py +++ b/docs/tutorials/06_DataAssociation-MultiTargetTutorial.py @@ -73,10 +73,11 @@ # %% # Generate ground truth # ^^^^^^^^^^^^^^^^^^^^^ +from ordered_set import OrderedSet np.random.seed(1991) -truths = set() +truths = OrderedSet() transition_model = CombinedLinearGaussianTransitionModel([ConstantVelocity(0.005), ConstantVelocity(0.005)]) @@ -93,7 +94,7 @@ truth.append(GroundTruthState( transition_model.function(truth[k-1], noise=True, time_interval=timedelta(seconds=1)), timestamp=start_time+timedelta(seconds=k))) -truths.add(truth) +_ = truths.add(truth) # %% # Plot the ground truth diff --git a/docs/tutorials/08_JPDATutorial.py b/docs/tutorials/08_JPDATutorial.py index 8b7129b8a..6ae040c74 100644 --- a/docs/tutorials/08_JPDATutorial.py +++ b/docs/tutorials/08_JPDATutorial.py @@ -65,6 +65,7 @@ from datetime import datetime from datetime import timedelta +from ordered_set import OrderedSet import numpy as np from scipy.stats import uniform @@ -77,7 +78,7 @@ np.random.seed(1991) -truths = set() +truths = OrderedSet() start_time = datetime.now() transition_model = CombinedLinearGaussianTransitionModel([ConstantVelocity(0.005), diff --git a/docs/tutorials/09_Initiators_&_Deleters.py b/docs/tutorials/09_Initiators_&_Deleters.py index c8f969e65..89eaddd55 100644 --- a/docs/tutorials/09_Initiators_&_Deleters.py +++ b/docs/tutorials/09_Initiators_&_Deleters.py @@ -20,6 +20,7 @@ from datetime import timedelta import numpy as np +from ordered_set import OrderedSet from stonesoup.models.transition.linear import CombinedLinearGaussianTransitionModel, \ ConstantVelocity @@ -28,7 +29,7 @@ np.random.seed(1991) start_time = datetime.now() -truths = set() # Truths across all time +truths = OrderedSet() # Truths across all time current_truths = set() # Truths alive at current time transition_model = CombinedLinearGaussianTransitionModel([ConstantVelocity(0.005), diff --git a/docs/tutorials/filters/GMPHDTutorial.py b/docs/tutorials/filters/GMPHDTutorial.py index 4252e0afd..03480700d 100644 --- a/docs/tutorials/filters/GMPHDTutorial.py +++ b/docs/tutorials/filters/GMPHDTutorial.py @@ -110,6 +110,7 @@ plt.style.use('seaborn-colorblind') # Other general imports import numpy as np +from ordered_set import OrderedSet from datetime import datetime, timedelta start_time = datetime.now() @@ -129,7 +130,7 @@ from stonesoup.types.groundtruth import GroundTruthPath, GroundTruthState start_time = datetime.now() -truths = set() # Truths across all time +truths = OrderedSet() # Truths across all time current_truths = set() # Truths alive at current time start_truths = set() number_steps = 20 diff --git a/docs/tutorials/sensormanagement/01_SingleSensorManagement.py b/docs/tutorials/sensormanagement/01_SingleSensorManagement.py index 7717badd2..a0298054f 100644 --- a/docs/tutorials/sensormanagement/01_SingleSensorManagement.py +++ b/docs/tutorials/sensormanagement/01_SingleSensorManagement.py @@ -99,6 +99,7 @@ import numpy as np import random +from ordered_set import OrderedSet from datetime import datetime, timedelta start_time = datetime.now() @@ -128,7 +129,7 @@ ConstantVelocity(0.005)]) yps = range(0, 100, 10) # y value for prior state -truths = [] +truths = OrderedSet() ntruths = 3 # number of ground truths in simulation time_max = 50 # timestamps the simulation is observed over @@ -144,7 +145,7 @@ truth.append( GroundTruthState(transition_model.function(truth[k - 1], noise=True, time_interval=timedelta(seconds=1)), timestamp=start_time + timedelta(seconds=k))) - truths.append(truth) + truths.add(truth) # alternate directions when initiating tracks xdirection *= -1 @@ -156,11 +157,8 @@ from stonesoup.plotter import Plotterly -# Stonesoup plotter requires sets not lists -truths_set = set(truths) - plotter = Plotterly() -plotter.plot_ground_truths(truths_set, [0, 2]) +plotter.plot_ground_truths(truths, [0, 2]) plotter.fig # %% @@ -249,14 +247,10 @@ from stonesoup.types.track import Track # Initialise tracks from the RandomSensorManager -tracksA = [] -for j, prior in enumerate(priors): - tracksA.append(Track([prior])) +tracksA = {Track([prior]) for prior in priors} # Initialise tracks from the BruteForceSensorManager -tracksB = [] -for j, prior in enumerate(priors): - tracksB.append(Track([prior])) +tracksB = {Track([prior]) for prior in priors} # %% # Create sensor managers @@ -345,8 +339,6 @@ # Here the chosen target for observation is selected randomly using the method :meth:`choose_actions()` from the class # :class:`~.RandomSensorManager`. -from ordered_set import OrderedSet - # Generate list of timesteps from ground truth timestamps timesteps = [] for state in truths[0]: @@ -359,7 +351,7 @@ chosen_actions = randomsensormanager.choose_actions(tracksA, timestep) # Create empty dictionary for measurements - measurementsA = [] + measurementsA = set() for chosen_action in chosen_actions: for sensor, actions in chosen_action.items(): @@ -369,8 +361,7 @@ # Observe this ground truth # i.e. {z}k - measurements = sensorA.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) - measurementsA.extend(measurements) + measurementsA |= sensorA.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) hypotheses = data_associator.associate(tracksA, measurementsA, @@ -388,8 +379,8 @@ plotterA = Plotterly() plotterA.plot_sensors(sensorA) -plotterA.plot_ground_truths(truths_set, [0, 2]) -plotterA.plot_tracks(set(tracksA), [0, 2], uncertainty=True) +plotterA.plot_ground_truths(truths, [0, 2]) +plotterA.plot_tracks(tracksA, [0, 2], uncertainty=True) plotterA.fig # %% @@ -425,7 +416,7 @@ chosen_actions = bruteforcesensormanager.choose_actions(tracksB, timestep) # Create empty dictionary for measurements - measurementsB = [] + measurementsB = set() for chosen_action in chosen_actions: for sensor, actions in chosen_action.items(): @@ -435,8 +426,7 @@ # Observe this ground truth # i.e. {z}k - measurements = sensorB.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) - measurementsB.extend(measurements) + measurementsB |= sensorB.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) hypotheses = data_associator.associate(tracksB, measurementsB, @@ -453,8 +443,8 @@ plotterB = Plotterly() plotterB.plot_sensors(sensorB) -plotterB.plot_ground_truths(truths_set, [0, 2]) -plotterB.plot_tracks(set(tracksB), [0, 2], uncertainty=True) +plotterB.plot_ground_truths(truths, [0, 2]) +plotterB.plot_tracks(tracksB, [0, 2], uncertainty=True) plotterB.fig # %% diff --git a/docs/tutorials/sensormanagement/02_MultiSensorManagement.py b/docs/tutorials/sensormanagement/02_MultiSensorManagement.py index 3f7eac2aa..7597a19af 100644 --- a/docs/tutorials/sensormanagement/02_MultiSensorManagement.py +++ b/docs/tutorials/sensormanagement/02_MultiSensorManagement.py @@ -51,6 +51,7 @@ import numpy as np import random +from ordered_set import OrderedSet from datetime import datetime, timedelta start_time = datetime.now() @@ -79,7 +80,7 @@ ConstantVelocity(0.005)]) yps = range(0, 100, 10) # y value for prior state -truths = [] +truths = OrderedSet() ntruths = 3 # number of ground truths in simulation time_max = 50 # timestamps the simulation is observed over @@ -95,7 +96,7 @@ truth.append( GroundTruthState(transition_model.function(truth[k - 1], noise=True, time_interval=timedelta(seconds=1)), timestamp=start_time + timedelta(seconds=k))) - truths.append(truth) + truths.add(truth) xdirection *= -1 if j % 2 == 0: @@ -107,10 +108,9 @@ from stonesoup.plotter import Plotterly # Stonesoup plotter requires sets not lists -truths_set = set(truths) plotter = Plotterly() -plotter.plot_ground_truths(truths_set, [0, 2]) +plotter.plot_ground_truths(truths, [0, 2]) plotter.fig # %% @@ -211,14 +211,10 @@ from stonesoup.types.track import Track # Initialise tracks from the RandomSensorManager -tracksA = [] -for j, prior in enumerate(priors): - tracksA.append(Track([prior])) +tracksA = {Track([prior]) for prior in priors} # Initialise tracks from the BruteForceSensorManager -tracksB = [] -for j, prior in enumerate(priors): - tracksB.append(Track([prior])) +tracksB = {Track([prior]) for prior in priors} # %% # Create sensor managers @@ -322,7 +318,7 @@ chosen_actions = randomsensormanager.choose_actions(tracksA, timestep) # Create empty dictionary for measurements - measurementsA = [] + measurementsA = set() for chosen_action in chosen_actions: for sensor, actions in chosen_action.items(): @@ -332,8 +328,7 @@ sensor.act(timestep) # Observe this ground truth - measurements = sensor.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) - measurementsA.extend(measurements) + measurementsA |= sensor.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) hypotheses = data_associator.associate(tracksA, measurementsA, @@ -352,8 +347,8 @@ plotterA = Plotterly() plotterA.plot_sensors(sensor_setA) -plotterA.plot_ground_truths(truths_set, [0, 2]) -plotterA.plot_tracks(set(tracksA), [0, 2], uncertainty=True) +plotterA.plot_ground_truths(truths, [0, 2]) +plotterA.plot_tracks(tracksA, [0, 2], uncertainty=True) plotterA.fig # %% @@ -393,7 +388,7 @@ chosen_actions = bruteforcesensormanager.choose_actions(tracksB, timestep) # Create empty dictionary for measurements - measurementsB = [] + measurementsB = set() for chosen_action in chosen_actions: for sensor, actions in chosen_action.items(): @@ -403,8 +398,7 @@ sensor.act(timestep) # Observe this ground truth - measurements = sensor.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) - measurementsB.extend(measurements) + measurementsB |= sensor.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) hypotheses = data_associator.associate(tracksB, measurementsB, @@ -422,8 +416,8 @@ plotterB = Plotterly() plotterB.plot_sensors(sensor_setB) -plotterB.plot_ground_truths(truths_set, [0, 2]) -plotterB.plot_tracks(set(tracksB), [0, 2], uncertainty=True) +plotterB.plot_ground_truths(truths, [0, 2]) +plotterB.plot_tracks(tracksB, [0, 2], uncertainty=True) plotterB.fig # %% diff --git a/docs/tutorials/sensormanagement/03_OptimisedSensorManagement.py b/docs/tutorials/sensormanagement/03_OptimisedSensorManagement.py index 7ed317050..cc1344e94 100644 --- a/docs/tutorials/sensormanagement/03_OptimisedSensorManagement.py +++ b/docs/tutorials/sensormanagement/03_OptimisedSensorManagement.py @@ -44,6 +44,7 @@ import numpy as np import random +from ordered_set import OrderedSet from datetime import datetime, timedelta start_time = datetime.now() @@ -72,7 +73,7 @@ ConstantVelocity(0.005)]) yps = range(0, 100, 10) # y value for prior state -truths = [] +truths = OrderedSet() ntruths = 3 # number of ground truths in simulation time_max = 50 # timestamps the simulation is observed over @@ -88,7 +89,7 @@ truth.append( GroundTruthState(transition_model.function(truth[k - 1], noise=True, time_interval=timedelta(seconds=1)), timestamp=start_time + timedelta(seconds=k))) - truths.append(truth) + truths.add(truth) xdirection *= -1 if j % 2 == 0: @@ -100,10 +101,9 @@ from stonesoup.plotter import Plotterly # Stonesoup plotter requires sets not lists -truths_set = set(truths) plotter = Plotterly() -plotter.plot_ground_truths(truths_set, [0, 2]) +plotter.plot_ground_truths(truths, [0, 2]) plotter.fig # %% @@ -217,19 +217,13 @@ from stonesoup.types.track import Track # Initialise tracks from the BruteForceSensorManager -tracksA = [] -for j, prior in enumerate(priors): - tracksA.append(Track([prior])) +tracksA = {Track([prior]) for prior in priors} # Initialise tracks from the OptimizeBruteSensorManager -tracksB = [] -for j, prior in enumerate(priors): - tracksB.append(Track([prior])) +tracksB = {Track([prior]) for prior in priors} # Initialise tracks from the OptimizeBasinHoppingSensorManager -tracksC = [] -for j, prior in enumerate(priors): - tracksC.append(Track([prior])) +tracksC = {Track([prior]) for prior in priors} # %% # Create sensor managers @@ -329,7 +323,7 @@ chosen_actions = bruteforcesensormanager.choose_actions(tracksA, timestep) # Create empty dictionary for measurements - measurementsA = [] + measurementsA = set() for chosen_action in chosen_actions: for sensor, actions in chosen_action.items(): @@ -339,8 +333,7 @@ sensor.act(timestep) # Observe this ground truth - measurements = sensor.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) - measurementsA.extend(measurements) + measurementsA |= sensor.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) hypotheses = data_associator.associate(tracksA, measurementsA, @@ -361,7 +354,7 @@ plotterA = Plotterly() plotterA.plot_sensors(sensor_setA) -plotterA.plot_ground_truths(truths_set, [0, 2]) +plotterA.plot_ground_truths(truths, [0, 2]) plotterA.plot_tracks(set(tracksA), [0, 2], uncertainty=True) plotterA.fig @@ -381,7 +374,7 @@ chosen_actions = optimizebrutesensormanager.choose_actions(tracksB, timestep) # Create empty dictionary for measurements - measurementsB = [] + measurementsB = set() for chosen_action in chosen_actions: for sensor, actions in chosen_action.items(): @@ -391,8 +384,7 @@ sensor.act(timestep) # Observe this ground truth - measurements = sensor.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) - measurementsB.extend(measurements) + measurementsB |= sensor.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) hypotheses = data_associator.associate(tracksB, measurementsB, @@ -412,8 +404,8 @@ plotterB = Plotterly() plotterB.plot_sensors(sensor_setB) -plotterB.plot_ground_truths(truths_set, [0, 2]) -plotterB.plot_tracks(set(tracksB), [0, 2], uncertainty=True) +plotterB.plot_ground_truths(truths, [0, 2]) +plotterB.plot_tracks(tracksB, [0, 2], uncertainty=True) plotterB.fig # %% @@ -429,7 +421,7 @@ chosen_actions = optimizebasinhoppingsensormanager.choose_actions(tracksC, timestep) # Create empty dictionary for measurements - measurementsC = [] + measurementsC = set() for chosen_action in chosen_actions: for sensor, actions in chosen_action.items(): @@ -439,8 +431,7 @@ sensor.act(timestep) # Observe this ground truth - measurements = sensor.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) - measurementsC.extend(measurements) + measurementsC |= sensor.measure(OrderedSet(truth[timestep] for truth in truths), noise=True) hypotheses = data_associator.associate(tracksC, measurementsC, @@ -460,8 +451,8 @@ plotterC = Plotterly() plotterC.plot_sensors(sensor_setC) -plotterC.plot_ground_truths(truths_set, [0, 2]) -plotterC.plot_tracks(set(tracksC), [0, 2], uncertainty=True) +plotterC.plot_ground_truths(truths, [0, 2]) +plotterC.plot_tracks(tracksC, [0, 2], uncertainty=True) plotterC.fig # %%