From 3c4943be0cf7405d8e50fd9ed800d237fe2f98ff Mon Sep 17 00:00:00 2001
From: Lewin Probst <info@emirror.de>
Date: Fri, 15 May 2020 17:13:36 +0200
Subject: [PATCH] Introduced backward tracking feature.

---
 VERSION                                       |  2 +-
 lib/+artoa/+controller/+main/open.m           |  1 +
 .../+parameter/checkboxBackwardTracking.m     | 22 ++++++++++
 .../+parameter/getDefaultCombinationCell.m    | 17 +++++++-
 .../+track/+parameter/initialize.m            |  1 +
 .../+controller/+track/+parameter/updateGui.m |  2 +
 lib/+artoa/+gui/main.m                        | 12 ++++++
 lib/+artoa/+trajectory/calculate.m            | 11 ++++-
 .../+trajectory/calculateCombinationSegment.m | 40 ++++++++++++++++++-
 .../+versioning/+migrations/versions/v4208.m  |  4 ++
 10 files changed, 105 insertions(+), 7 deletions(-)
 create mode 100644 lib/+artoa/+controller/+track/+parameter/checkboxBackwardTracking.m
 create mode 100644 lib/+artoa/+versioning/+migrations/versions/v4208.m

diff --git a/VERSION b/VERSION
index bea0d09..274ccca 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-207
\ No newline at end of file
+209
\ No newline at end of file
diff --git a/lib/+artoa/+controller/+main/open.m b/lib/+artoa/+controller/+main/open.m
index 967fb56..c220fcf 100644
--- a/lib/+artoa/+controller/+main/open.m
+++ b/lib/+artoa/+controller/+main/open.m
@@ -34,6 +34,7 @@ callbacks.convertProfilesToRfb = @artoa.controller.file.profile2rfb.open;
 
 %% Prepare callbacks for track parameter
 callbacks.checkboxDopplerCorrection = @artoa.controller.track.parameter.checkboxDopplerCorrection;
+callbacks.checkboxBackwardTracking = @artoa.controller.track.parameter.checkboxBackwardTracking;
 callbacks.comboboxInterpolationMethod = @artoa.controller.track.parameter.comboboxInterpolationMethod;
 callbacks.comboboxSoundspeedMethod = @artoa.controller.track.parameter.comboboxSoundspeedMethod;
 callbacks.checkboxPlotResiduals = @artoa.controller.track.parameter.checkboxPlotResiduals;
diff --git a/lib/+artoa/+controller/+track/+parameter/checkboxBackwardTracking.m b/lib/+artoa/+controller/+track/+parameter/checkboxBackwardTracking.m
new file mode 100644
index 0000000..1e9aeb6
--- /dev/null
+++ b/lib/+artoa/+controller/+track/+parameter/checkboxBackwardTracking.m
@@ -0,0 +1,22 @@
+function [newValue] = checkboxBackwardTracking(~, ~)
+%CHECKBOXDOPPLERCORRECTION Summary of this function goes here
+%   Detailed explanation goes here
+
+global artoaGui artoaWorkspace;
+
+newValue = logical(artoaGui.trackParameter.checkboxBackwardTracking.Value);
+
+artoaWorkspace.trackParameter.enableBackwardTracking = newValue;
+
+%% Flip current soundsource combination table
+
+artoaWorkspace.trackParameter.soundsourceCombinations = ...
+    flipud(artoaWorkspace.trackParameter.soundsourceCombinations);
+begin = artoaWorkspace.trackParameter.soundsourceCombinations.combinationBegin;
+artoaWorkspace.trackParameter.soundsourceCombinations.combinationBegin = ...
+    artoaWorkspace.trackParameter.soundsourceCombinations.combinationEnd;
+artoaWorkspace.trackParameter.soundsourceCombinations.combinationEnd = begin;
+
+artoa.controller.track.parameter.updateGui();
+
+end
\ No newline at end of file
diff --git a/lib/+artoa/+controller/+track/+parameter/getDefaultCombinationCell.m b/lib/+artoa/+controller/+track/+parameter/getDefaultCombinationCell.m
index 697b6e9..4a21536 100644
--- a/lib/+artoa/+controller/+track/+parameter/getDefaultCombinationCell.m
+++ b/lib/+artoa/+controller/+track/+parameter/getDefaultCombinationCell.m
@@ -11,13 +11,26 @@ referencePosition = '';
 isNotNan = ~isnan(artoaWorkspace.satData.lat_sat) & ~isnan(artoaWorkspace.satData.lon_sat);
 knownPositions = [artoaWorkspace.satData.lat_sat(isNotNan), artoaWorkspace.satData.lon_sat(isNotNan)];
 if ~(size(knownPositions, 1) == 0)
+    if artoaWorkspace.trackParameter.enableBackwardTracking
+        referencePosition = [num2str(knownPositions(end, 1)) ' ' num2str(knownPositions(end, 2))];
+    else
         referencePosition = [num2str(knownPositions(1, 1)) ' ' num2str(knownPositions(1, 2))];
+    end
+end
+
+%% Set start and end date
+if ~artoaWorkspace.trackParameter.enableBackwardTracking
+    startDate = floor(min(artoaWorkspace.toaData.toaDate(artoaWorkspace.toaData.status ~= 2)));
+    endDate = floor(max(artoaWorkspace.toaData.toaDate(artoaWorkspace.toaData.status ~= 2)));
+else
+    startDate = floor(max(artoaWorkspace.toaData.toaDate(artoaWorkspace.toaData.status ~= 2)));
+    endDate = floor(min(artoaWorkspace.toaData.toaDate(artoaWorkspace.toaData.status ~= 2)));
 end
 
 %% Create default cell
 emptyCell = { ...
-    floor(min(artoaWorkspace.toaData.toaDate(artoaWorkspace.toaData.status ~= 2))), ...
-    floor(max(artoaWorkspace.toaData.toaDate(artoaWorkspace.toaData.status ~= 2))), ...
+    startDate, ...
+    endDate, ...
     '', ...
     referencePosition, ...
     1464, ...
diff --git a/lib/+artoa/+controller/+track/+parameter/initialize.m b/lib/+artoa/+controller/+track/+parameter/initialize.m
index 095848f..45291b1 100644
--- a/lib/+artoa/+controller/+track/+parameter/initialize.m
+++ b/lib/+artoa/+controller/+track/+parameter/initialize.m
@@ -14,6 +14,7 @@ callbacks = artoaGui.callbacks.main;
 %% Create workspace variables
 if pForceOverwrite || ~isfield(artoaWorkspace, 'trackParameter')
     artoaWorkspace.trackParameter = struct();
+    artoaWorkspace.trackParameter.enableBackwardTracking = false;
     
     % setup sound source combinations
     artoaWorkspace.trackParameter.soundsourceCombinations = ...
diff --git a/lib/+artoa/+controller/+track/+parameter/updateGui.m b/lib/+artoa/+controller/+track/+parameter/updateGui.m
index ed3c64e..71737b2 100644
--- a/lib/+artoa/+controller/+track/+parameter/updateGui.m
+++ b/lib/+artoa/+controller/+track/+parameter/updateGui.m
@@ -16,6 +16,8 @@ for i = 1:length(fieldNames)
     switch fieldNames{i}
         case 'dopplerCorrection'
             artoaGui.trackParameter.checkboxDopplerCorrection.Value = currentValue;
+        case 'enableBackwardTracking'
+            artoaGui.trackParameter.checkboxBackwardTracking.Value = currentValue;
         case 'plotResiduals'
             artoaGui.trackParameter.checkboxPlotResiduals.Value = currentValue;
         case 'trackingMethodValue'
diff --git a/lib/+artoa/+gui/main.m b/lib/+artoa/+gui/main.m
index 377d66a..21f3983 100644
--- a/lib/+artoa/+gui/main.m
+++ b/lib/+artoa/+gui/main.m
@@ -25,6 +25,7 @@ availableCallbacks = { ...
     'openTrackTrajectoryOutput', ...
     'switchHideDeletedDataPoints', ...
     'checkboxDopplerCorrection', ... % FIRST ITEM TRACK PARAMETER CALLBACKS
+    'checkboxBackwardTracking', ...
     'comboboxInterpolationMethod', ...
     'comboboxSoundspeedMethod', ...
     'checkboxPlotResiduals', ...
@@ -279,6 +280,17 @@ artoaGui.trackParameter.checkboxDopplerCorrection = uicontrol( ...
     'CallBack', pCallbacks.checkboxDopplerCorrection ...
 );
 
+artoaGui.trackParameter.checkboxBackwardTracking = uicontrol( ...
+    'Parent', artoaGui.trackParameter.frameOptions, ...
+    'String', 'Enable backward tracking', ...
+    'Style', 'checkbox', ...
+    'FontSize', 8, ...
+    'Units', 'normalized', ...
+    'Position', [left .1 .9 .3], ...
+    'Value', 0, ...
+    'CallBack', pCallbacks.checkboxBackwardTracking ...
+);
+
 % Interpolation method frame
 artoaGui.trackParameter.frameInterpolationMethod = uipanel( ...
     'Parent', artoaGui.trackParameter.frameTrackingParameter, ...
diff --git a/lib/+artoa/+trajectory/calculate.m b/lib/+artoa/+trajectory/calculate.m
index 093349c..52caa5b 100644
--- a/lib/+artoa/+trajectory/calculate.m
+++ b/lib/+artoa/+trajectory/calculate.m
@@ -227,11 +227,18 @@ for oCombination = 1:size(soundsourceCombinations, 1)
     elseif isempty(currentCombination.referencePosition{1})
         currentCombination.referencePosition{1} = num2str(trajectory(end, :));
     end
-    [segmentPositions, segmentDates, segmentClockError, segmentResiduals] = artoa.trajectory.calculateCombinationSegment( ...
+    
+    [ ...
+        segmentPositions, ...
+        segmentDates, ...
+        segmentClockError, ...
+        segmentResiduals ...
+        ] = artoa.trajectory.calculateCombinationSegment( ...
         preparedData, ...
         currentCombination, ...%trajectory(end, :), ...
         floatReferenceTime, ...
-        pSoundVelocity(oCombination, :) ...
+        pSoundVelocity(oCombination, :), ...
+        pTrackingParameter.enableBackwardTracking ...
     );
     
     % remove NaNs from segment
diff --git a/lib/+artoa/+trajectory/calculateCombinationSegment.m b/lib/+artoa/+trajectory/calculateCombinationSegment.m
index 3634792..46c46b8 100644
--- a/lib/+artoa/+trajectory/calculateCombinationSegment.m
+++ b/lib/+artoa/+trajectory/calculateCombinationSegment.m
@@ -1,4 +1,16 @@
-function [segmentPositions, segmentDates, segmentClockError, segmentResiduals] = calculateCombinationSegment(pCorrectedData, pCombinationDetails, pFloatReferenceTime, pSoundVelocity)
+function [ ...
+    segmentPositions, ...
+    segmentDates, ...
+    segmentClockError, ...
+    segmentResiduals ...
+    ] = ...
+    calculateCombinationSegment( ...
+        pCorrectedData, ...
+        pCombinationDetails, ...
+        pFloatReferenceTime, ...
+        pSoundVelocity, ...
+        pBackwardTracking ...
+    )
 %CALCULATECOMBINATIONSEGMENT Combination segment calculation.
 %   Using the input data, the function calculates the segment positions,
 %   its corresponding dates as well as the clock error (in case of hyperbolic calculation)
@@ -20,6 +32,8 @@ function [segmentPositions, segmentDates, segmentClockError, segmentResiduals] =
 %           used.
 %           For all other methods, only one value needs to be set.
 %           Unit: [m/s]
+%       pBackwardTracking (bool):
+%           If true, the data will be prepared for backward tracking
 %
 %   Returns:
 %       segmentPositions (double):
@@ -54,11 +68,18 @@ for i = 2:length(soundsourceNames)
 end
 
 %% Remove all dates that are out of bounds
+if pBackwardTracking
+    tmp = segmentStart;
+    segmentStart = segmentEnd;
+    segmentEnd = tmp;
+end
+
 intersectedToaDates = intersectedToaDates( ...
     intersectedToaDates >= segmentStart ...
     & intersectedToaDates <= segmentEnd ...
 );
 
+
 %% Create a table for every soundsource (required by tracking plugin system)
 pluginTables = struct();
 for i = 1:length(soundsourceNames)
@@ -110,7 +131,15 @@ for oDates = 1:lenIntersectedToaDates
 end
 warning('on');
 
-% Call the corresponding tracking method from the plugin folder
+%% Backward tracking
+% if enabled, everything needs to be upside down for the calculation
+if pBackwardTracking
+    for i = 1:length(soundsourceNames)
+        pluginTables.(soundsourceNames{i}) = flipud(pluginTables.(soundsourceNames{i}));
+    end
+end
+
+%% Call the corresponding tracking method from the plugin folder
 [segmentPositions, segmentClockError] = artoa.plugins.tracking.callTrackingMethod( ...
     trackingMethod, ...
     pluginTables, ...
@@ -118,6 +147,13 @@ warning('on');
     pCombinationDetails ...
     );
 
+%% Restore backward tracking changes
+% if enabled, the calculated positions need to be flipped upside down to be
+% able to display them correctly
+if pBackwardTracking
+    segmentPositions = flipud(segmentPositions);
+    segmentClockError = flipud(segmentClockError);
+end
 
 %% Store toa dates
 segmentDates = intersectedToaDates;
diff --git a/lib/+artoa/+versioning/+migrations/versions/v4208.m b/lib/+artoa/+versioning/+migrations/versions/v4208.m
new file mode 100644
index 0000000..f891d8f
--- /dev/null
+++ b/lib/+artoa/+versioning/+migrations/versions/v4208.m
@@ -0,0 +1,4 @@
+%% Backward tracking features
+if ~artoa.data.hasMember(artoaWorkspace, 'trackParameter', 'enableBackwardTracking')
+    artoaWorkspace.trackParameter.enableBackwardTracking = false;
+end
-- 
GitLab