diff --git a/lib/+artoa/+controller/+track/+trajectoryOutput/clearTrajectoryPlot.m b/lib/+artoa/+controller/+track/+trajectoryOutput/clearTrajectoryPlot.m index dd04086417f06df7ff669fd966728345dfb9eb20..8234647b63ba8e9908d09c7ef31b622b6895bb50 100644 --- a/lib/+artoa/+controller/+track/+trajectoryOutput/clearTrajectoryPlot.m +++ b/lib/+artoa/+controller/+track/+trajectoryOutput/clearTrajectoryPlot.m @@ -35,8 +35,13 @@ end for i = 1:length(trajectories) fnames = fieldnames(trajectories{i}); for k = 1:length(fnames) - if isvalid(trajectories{i}.(fnames{k})) - delete(trajectories{i}.(fnames{k})); + switch fnames{k} + case {'textReferencePoints', 'textPositions'} + cellfun(@delete, trajectories{i}.(fnames{k})); + otherwise + if isvalid(trajectories{i}.(fnames{k})) + delete(trajectories{i}.(fnames{k})); + end end end end diff --git a/lib/+artoa/+controller/+track/+trajectoryOutput/plot.m b/lib/+artoa/+controller/+track/+trajectoryOutput/plot.m index 5d19370982178b4afab8655619b53cbebd8a1244..e29cb8d274426484c0576753cd3fb4aa662f8880 100644 --- a/lib/+artoa/+controller/+track/+trajectoryOutput/plot.m +++ b/lib/+artoa/+controller/+track/+trajectoryOutput/plot.m @@ -40,11 +40,17 @@ for i = 1:length(trajectories) if trajectories{i}.hidden continue; end + trajectoryColor = artoaWorkspace.soundsourceColors(mod(trajectories{i}.id, size(artoaWorkspace.soundsourceColors, 1)), :); % plot the trajectory itself - [artoaGui.trajectoryOutput.trajectoryHandles{i}.scatterPositions] = ... + [ ... + artoaGui.trajectoryOutput.trajectoryHandles{i}.scatterPositions, ... + artoaGui.trajectoryOutput.trajectoryHandles{i}.linePositions, ... + artoaGui.trajectoryOutput.trajectoryHandles{i}.textPositions ... + ] = ... artoa.controller.track.trajectoryOutput.plotTrajectory( ... artoaGui.trajectoryOutput.axesTrajectoryOutput, ... - trajectories{i} ... + trajectories{i}, ... + trajectoryColor ... ); % plot trajectory reference point [ ... @@ -52,7 +58,8 @@ for i = 1:length(trajectories) artoaGui.trajectoryOutput.trajectoryHandles{i}.textReferencePoints ... ] = artoa.trajectory.plotTrajectoryReferencePositions( ... artoaGui.trajectoryOutput.axesTrajectoryOutput, ... - trajectories{i} ... + trajectories{i}, ... + trajectoryColor ... ); end diff --git a/lib/+artoa/+controller/+track/+trajectoryOutput/plotTrajectory.m b/lib/+artoa/+controller/+track/+trajectoryOutput/plotTrajectory.m index 7ddec199340a9c373b415a369593a0ed31eaaa53..dab4895a3309a8e9ab84ef503bf7c02621f21578 100644 --- a/lib/+artoa/+controller/+track/+trajectoryOutput/plotTrajectory.m +++ b/lib/+artoa/+controller/+track/+trajectoryOutput/plotTrajectory.m @@ -1,18 +1,43 @@ -function [scatterHandle] = plotTrajectory(pAxesHandle, pTrajectory) +function [scatterHandle, lineHandle, textHandles] = plotTrajectory(pAxesHandle, pTrajectory, pColor) %PLOTTRAJECTORY Summary of this function goes here % Detailed explanation goes here %% Update track gui content hold(pAxesHandle, 'on'); -% plot trajectory positions +%% Plot trajectory positions scatterHandle = ... scatter( ... pAxesHandle, ... pTrajectory.longitude, ... - pTrajectory.latitude ... + pTrajectory.latitude, ... + 6, ... + pColor, ... + 'filled' ... ); +%% Plot trajectory line +lineHandle = line( ... + pAxesHandle, ... + pTrajectory.longitude, ... + pTrajectory.latitude, ... + 'Color', pColor ... +); + +%% Plot text next to trajectory +t = artoa.convert.rd2dmy(pTrajectory.date); + +textHandles = cell(1, length(t)); +for i = 1:15:length(t) + textHandles{i} = text( ... + pTrajectory.longitude(i), ... + pTrajectory.latitude(i), ... + {' '; [num2str(t(i, 3)) '-' pad(num2str(t(i, 2)), 2, 'left', '0') '-' pad(num2str(t(i, 1)), 2, 'left', '0')]}, ... + 'FontSize', 6, ... + 'Color', pColor ... + ); +end + hold(pAxesHandle, 'off'); diff --git a/lib/+artoa/+controller/+track/run.m b/lib/+artoa/+controller/+track/run.m index fcb6ace13ceaad1c39ba2726b1f72f669fc86ab8..228595e0f1ad01acaeb33eda97eda3f457ff488c 100644 --- a/lib/+artoa/+controller/+track/run.m +++ b/lib/+artoa/+controller/+track/run.m @@ -21,7 +21,7 @@ end %% Calculate and append track -trajectory = artoa.float.calculateTrajectory( ... +[trajectory, trajectoryDates] = artoa.float.calculateTrajectory( ... artoaWorkspace.float, ... artoaWorkspace.toaData, ... artoaWorkspace.filteredSoundsources, ... @@ -45,7 +45,8 @@ trajectoryObject.trackParameter = artoaWorkspace.trackParameter; % trajectory contains [lat lon] trajectoryObject.latitude = trajectory(:, 1); trajectoryObject.longitude = trajectory(:, 2); -trajectoryObject.id = length(artoaWorkspace.trajectoryOutput.trajectories) + 1; +trajectoryObject.date = trajectoryDates; +trajectoryObject.id = artoaWorkspace.trajectoryOutput.trajectories{end}.id + 1; trajectoryObject.hidden = false; % store to workspace diff --git a/lib/+artoa/+convert/rd2dmy.m b/lib/+artoa/+convert/rd2dmy.m index f4cd8eea00ef1a0224bb08c765593d7a18d54e61..f855975b0ba8a062fb89886ac59cd097ee7102ec 100644 --- a/lib/+artoa/+convert/rd2dmy.m +++ b/lib/+artoa/+convert/rd2dmy.m @@ -13,6 +13,6 @@ rjul = rjul(:); % redifined RAFOS day %date = greg_0h(rjul+2440000); -date = greg_0h(rjul+2451545); +date = artoa.vendor.greg_0h(rjul+2451545); dmy = [date(:,3) date(:,2) date(:,1)]; diff --git a/lib/+artoa/+data/calculateCombinationSegmentLeastSquares.m b/lib/+artoa/+data/calculateCombinationSegmentLeastSquares.m index 832cf299816617eba899eb05111719a08dfa9957..d66ccf3116a059dcbdcf805410e282c503049cab 100644 --- a/lib/+artoa/+data/calculateCombinationSegmentLeastSquares.m +++ b/lib/+artoa/+data/calculateCombinationSegmentLeastSquares.m @@ -1,4 +1,4 @@ -function [segmentPositions] = calculateCombinationSegmentLeastSquares(pCorrectedData, pCombinationDetails, pFloatReferenceTime, pSoundVelocity) +function [segmentPositions, segmentDates] = calculateCombinationSegmentLeastSquares(pCorrectedData, pCombinationDetails, pFloatReferenceTime, pSoundVelocity) %CALCULATECOMBINATIONSEGMENTLEASTSQUARES Summary of this function goes here % Detailed explanation goes here @@ -80,6 +80,9 @@ for oDates = 1:length(intersectedToaDates) ]; end +%% Store toa dates +segmentDates = intersectedToaDates; + %% Remove reference position from trajectory segmentPositions = segmentPositions(2:end, :); diff --git a/lib/+artoa/+float/calculateTrajectory.m b/lib/+artoa/+float/calculateTrajectory.m index 5a17b24f81503c57938e8a6ccb4bb1ce81b887e5..c92b94ed4613dfd474307cb2ef6b216d13d7b4d5 100644 --- a/lib/+artoa/+float/calculateTrajectory.m +++ b/lib/+artoa/+float/calculateTrajectory.m @@ -1,4 +1,4 @@ -function [trajectory] = calculateTrajectory(pFloatDetails, pToaData, pSoundsources, pTrackingParameter, pLeapsecondsMatrix) +function [trajectory, trajectoryDates] = calculateTrajectory(pFloatDetails, pToaData, pSoundsources, pTrackingParameter, pLeapsecondsMatrix) %CALCULATETRAJECTORY Summary of this function goes here % Detailed explanation goes here @@ -178,12 +178,15 @@ trajectory = []; switch (trackingMethod) case 'least square' - trajectory = artoa.float.calculateTrajectoryLeastSquares( ... + [trajectory, trajectoryDates] = artoa.float.calculateTrajectoryLeastSquares( ... preparedData, ... soundsourceCombinations, ...startPosition, ... floatReferenceTime, ... soundVelocity ... ); + case 'exclusive least square' + trajectory = artoa.float.calculateTrajectoryExclusiveLeastSquares( ... + ); end return @@ -211,162 +214,4 @@ end % clkerror = NaN; -return - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -%% Get required data -soundsourceCombinations = pTrackingParameter.soundsourceCombinations; -trackingMethod = pTrackingParameter.trackingMethodString; -startPosition = [pSatData.lat_sat(1) pSatData.lon_sat(1)]; - - -%% Run through all combinations - -% get the current combination -currentCombination = soundsourceCombinations(1, :); -% isolate the sound source data of this combination -currentSources = artoa.data.extractSoundsourcesFromStruct( ... - strsplit(currentCombination{3}), pSoundsources ... -); -% get the rafos date boundaries for this combination -beginRafosDate = str2double(currentCombination{1}); -endRafosDate = str2double(currentCombination{2}); -% create a selection based on the information above - -% equals to true if the dates are in range -selectionOfDates = (pToaData.toaDate >= beginRafosDate) & (pToaData.toaDate <= endRafosDate); - -soundsourceData = struct(); -soundsourcePositions = []; -for oSoundsource = 1:length(currentSources) - % collect the toa points that have been applied to the sound source and - % is in date range - selectionSoundsource = ... - strcmp(pToaData.soundSource, {currentSources{oSoundsource}.sourcename}) ... - & selectionOfDates; - [soundsourceData(oSoundsource).rafosDate, sortIndices] = sort(pToaData.toaDate(selectionSoundsource)); - soundsourceData(oSoundsource).toa = pToaData.toa(selectionSoundsource); - % sort toa - soundsourceData(oSoundsource).toa = soundsourceData(oSoundsource).toa(sortIndices); - % get position - soundsourcePositions = [soundsourcePositions; currentSources{oSoundsource}.position]; -end - -% search all correspondences -sameDateIndices = []; -for oDate = 1:length(soundsourceData(1).rafosDate) - tmpDate = soundsourceData(1).rafosDate(oDate); - tmpDateExists = true; - tmpIndices = oDate; - for oSoundsource = 2:length(currentSources) - tmpDateExists = tmpDateExists & any(soundsourceData(oSoundsource).rafosDate == tmpDate); - tmpIndices = [tmpIndices, find(soundsourceData(oSoundsource).rafosDate == tmpDate)]; - end - if tmpDateExists - sameDateIndices(end + 1, :) = tmpIndices; - end -end - - -for oSoundsource = 1:length(currentSources) - soundsourceData(oSoundsource).distanceToSoundsource = ... - (soundsourceData(oSoundsource).toa ... - + (pFloatDetails.phasereftime(1)*60 + pFloatDetails.phasereftime(2)) * 60 ... - - (currentSources{oSoundsource}.reftime(:, 1)*3600 + currentSources{oSoundsource}.reftime(:, 2) * 60) ... % - leapseconds missing - ) * 1464; -end - -calculatedPositions = startPosition; - -for oIndex = 1:size(sameDateIndices, 1) - sv = 1.464; - calculatedPositions = [ ... - calculatedPositions; ... - artoa.vendor.ls_converge( ... - calculatedPositions(end, :), ... - length(currentSources), ... - soundsourcePositions, ... - [soundsourceData(1).distanceToSoundsource(sameDateIndices(oIndex));soundsourceData(2).distanceToSoundsource(sameDateIndices(oIndex))], ... - sv ... - )* 180 / pi ... - ]; -end - -% run through all dates -indicesDates = find(selectionOfDates); -for oDates = 1:length(indicesDates) - % get the toa - currentToa = pToaData.toa(indicesDates(oDates)); - -end - - - - -switch (trackingMethod) - case 'Least Square' -% gpsRafosDates(o) = artoa.convert.dmy2rd( ... -% gpsData(o, pRfb.SAT_FORMAT.day_sat), ... -% gpsData(o, pRfb.SAT_FORMAT.month_sat), ... -% gpsData(o, pRfb.SAT_FORMAT.year_sat) ... -% ); - %distanceSoundSourceToFloat = artoa.data.calculateGeodist(currentGpsPosition, soundSourcePosition); -end - - -trajectory = []; - -end \ No newline at end of file +return \ No newline at end of file diff --git a/lib/+artoa/+float/calculateTrajectoryLeastSquares.m b/lib/+artoa/+float/calculateTrajectoryLeastSquares.m index 7bb2874606eadfc5d89870484fc7b6df86da8e50..dc36489fd99ed3ea7794c4edb9c04ec27388f4c8 100644 --- a/lib/+artoa/+float/calculateTrajectoryLeastSquares.m +++ b/lib/+artoa/+float/calculateTrajectoryLeastSquares.m @@ -1,21 +1,23 @@ -function [trajectory] = calculateTrajectoryLeastSquares(pPreparedData, pSoundsourceCombinations, pFloatReferenceTime, pSoundVelocity) +function [trajectory, trajectoryDates] = calculateTrajectoryLeastSquares(pPreparedData, pSoundsourceCombinations, pFloatReferenceTime, pSoundVelocity) %CALCULATETRAJECTORYLEASTSQUARES Summary of this function goes here % Detailed explanation goes here trajectory = []; +trajectoryDates = []; %trajectory = pStartPosition; for oCombination = 1:size(pSoundsourceCombinations, 1) - segmentPositions = artoa.data.calculateCombinationSegmentLeastSquares( ... + [segmentPositions, segmentDates] = artoa.data.calculateCombinationSegmentLeastSquares( ... pPreparedData, ... pSoundsourceCombinations(oCombination, :), ...%trajectory(end, :), ... pFloatReferenceTime, ... - pSoundVelocity{1, oCombination} ... + pSoundVelocity.soundspeed1(oCombination) ... ); trajectory = [ ... trajectory; ... segmentPositions ... ]; + trajectoryDates = [trajectoryDates; segmentDates]; end end diff --git a/lib/+artoa/+float/scatterSatDataPositions.m b/lib/+artoa/+float/scatterSatDataPositions.m index 631fee15f831392b6fc661ddf21dc030bb8da486..cc5064565b19dcd1d08c7221c3f67b2857864cbb 100644 --- a/lib/+artoa/+float/scatterSatDataPositions.m +++ b/lib/+artoa/+float/scatterSatDataPositions.m @@ -16,13 +16,13 @@ steps = 1:3:(floor(length(x)/3)*3); %% Prepare text cell textCell = {}; for i = steps - textCell{end + 1} = {'', [' ' num2str(year(i)) '-' num2str(month(i)) '-' num2str(day(i))]}; + textCell{end + 1} = {'', [' ' num2str(year(i)) '-' pad(num2str(month(i)), 2, 'left', '0') '-' pad(num2str(day(i)), 2, 'left', '0')]}; end %% Plot hold(pAxesHandle, 'on'); -scatterHandle = scatter(pAxesHandle, x, y); -textHandles = text(pAxesHandle, x(steps), y(steps), textCell, 'FontSize', 7); +scatterHandle = scatter(pAxesHandle, x, y, [], [.5 .5 .5]); +textHandles = text(pAxesHandle, x(steps), y(steps), textCell, 'FontSize', 7, 'Color', [.5 .5 .5]); hold(pAxesHandle, 'off'); end diff --git a/lib/+artoa/+gui/+track/trajectoryOutput.m b/lib/+artoa/+gui/+track/trajectoryOutput.m index 6ecf440f178e06f57af39253f37928235098ab97..b74ac8424916b701c3deaa6fd7b6de61bc679b13 100644 --- a/lib/+artoa/+gui/+track/trajectoryOutput.m +++ b/lib/+artoa/+gui/+track/trajectoryOutput.m @@ -16,7 +16,8 @@ availableCallbacks = { ... 'checkboxTrackVisible', ... 'buttonTrackInfos', ... 'buttonVelocities', ... - 'tableGeneratedTracksSelect' ... + 'tableGeneratedTracksSelect', ... + 'buttonGenerateNewTrajectoryId' ... }; @@ -162,6 +163,16 @@ artoaGui.trajectoryOutput.checkboxMercator = uicontrol( ... 'CallBack', pCallbacks.checkboxMercator ... ); +artoaGui.trajectoryOutput.buttonGenerateNewTrajectoryId = uicontrol( ... + 'Parent', artoaGui.trajectoryOutput.frameDisplayOptions, ... + 'String', 'Generate new trajectory id', ... + 'Style', 'PushButton', ... + 'FontSize', 8, ... + 'Units', 'normalized', ... + 'Position', [.1 .6 .8 .175], ... + 'CallBack', pCallbacks.buttonGenerateNewTrajectoryId ... +); + artoaGui.trajectoryOutput.buttonTrackInfos = uicontrol( ... 'Parent', artoaGui.trajectoryOutput.frameDisplayOptions, ... 'String', 'Track infos', ... diff --git a/lib/+artoa/+soundsources/scatterPositions.m b/lib/+artoa/+soundsources/scatterPositions.m index 716c1b113fdb531e1e2365e9fc9026ad61a8bb68..82177be294a9887ab9818dd35c5a71fd05daa798 100644 --- a/lib/+artoa/+soundsources/scatterPositions.m +++ b/lib/+artoa/+soundsources/scatterPositions.m @@ -19,8 +19,8 @@ end %% Plot positions hold(pAxesHandle, 'on'); -scatterHandle = scatter(pAxesHandle, lon, lat); -textHandles = text(lon, lat, plot_names); +scatterHandle = scatter(pAxesHandle, lon, lat, [], [0 0 0]); +textHandles = text(lon, lat, plot_names, 'Color', [0 0 0]); hold(pAxesHandle, 'off'); end diff --git a/lib/+artoa/+trajectory/plotTrajectoryReferencePositions.m b/lib/+artoa/+trajectory/plotTrajectoryReferencePositions.m index 1cd95d2810438cf807e0488241fd8e655aa6c08f..7577493b1bf0e0366e6123f45b72523cf6fdee8c 100644 --- a/lib/+artoa/+trajectory/plotTrajectoryReferencePositions.m +++ b/lib/+artoa/+trajectory/plotTrajectoryReferencePositions.m @@ -1,4 +1,4 @@ -function [scatterHandles, textHandles] = plotTrajectoryReferencePositions(pAxesHandle, pTrajectory) +function [scatterHandles, textHandles] = plotTrajectoryReferencePositions(pAxesHandle, pTrajectory, pColor) %PLOTTRAJECTORYREFERENCEPOSITIONS Summary of this function goes here % Detailed explanation goes here @@ -15,12 +15,14 @@ y = referencePositions(:, 1); hold(pAxesHandle, 'on'); -scatterHandles = scatter(pAxesHandle, x, y, 'x'); +scatterHandles = scatter(pAxesHandle, x, y, [], pColor, 'x'); % Plot text +textHandles = cell(1, length(x)); for i = 1:length(x) - textHandles = text( ... - pAxesHandle, x(i), y(i), {'', [' ' num2str(pTrajectory.id) '.' num2str(i)]} ... + textHandles{i} = text( ... + pAxesHandle, x(i), y(i), {'', [' ' num2str(pTrajectory.id) '.' num2str(i)]}, ... + 'Color', pColor ... ); end