Newer
Older
leprob001
committed
function [ success ] = rfc(pFilename, pFloatDetails, pData, pTrajectory)
%RFC Saves the given data to the filename in RFC format.
%
% Parameters:
% pFilename (string) The destination filename.
% pFloatDetails (struct) The FLOAT section that is stored in an RFB
% file.
% pData (matrix) The data that should be written to the RFC file.
% Each line contains one set of data. The matrix format needs to
% be the following:
% IFLAG MESSAGE_NUMBER MESSAGE_DATE TEMP PRES LAT LON u v w
leprob001
committed
% pTrajectory (struct) The trajectory data according to the memory
% data format specification, see projects wiki.
%% Initialize return variables
success = false;
%% Initialize variables required for processing
leprob001
committed
headerString = '';
dataString = '';
%% Parameter check
parameterError = false;
leprob001
committed
if (~isstring(pFilename) && ~ischar(pFilename))
warning([mfilename ': Given filename is neither a string nor a char!']);
parameterError = true;
end
if (~isstruct(pFloatDetails))
warning([mfilename ': Given float details is not a struct!']);
parameterError = true;
end
expectedDataColumns = 10;
if (size(pData, 2) ~= expectedDataColumns)
warning([mfilename ': Given data has ' site(pData, 2) ' columns, but ' ...
num2str(expectedDataColumns) ' expected!']);
parameterError = true;
end
if (parameterError)
return;
else
clear parameterError;
end
%% Replace all NaN with default values
% defaultValues = repmat(-999, 10);
% defaultValues(4) = -9.99; % temperature default value
% % start at index 4 because the first three do not have default values
% for i = 4:size(pData, 2)
% nanIndex = find(isnan(pData(:, i)));
% if ~isempty(nanIndex)
% pData(nanIndex, i) = repmat(defaultValues(i), 1, size(pData, 1));
% end
% clear nanIndex;
% end
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
%% Prepare header and add it to the file string
% FLOAT NAME
floatname = num2str(pFloatDetails.floatname);
% FLOAT CYCLE
cycle = num2str(pFloatDetails.cycle(1));
% LAUNCH PARAMETER
launchPositionLat = num2str(pFloatDetails.cycle(2), '%3.2f');
launchPositionLon = num2str(pFloatDetails.cycle(3), '%3.2f');
launchTime = [pFloatDetails.launchtime, 0];
launchTimeRafosDays = num2str( ...
artoa.convert.dmy2rd(launchTime(3), launchTime(2), launchTime(1)) ...
);
launchTime = num2str(launchTime);
% RECOVER PARAMETER
recoverTime = [pFloatDetails.recovertime, 0];
recoverTimeRafosDays = num2str( ...
artoa.convert.dmy2rd(recoverTime(3), recoverTime(2), recoverTime(1)) ...
);
recoverTime = num2str(recoverTime);
% FIRST SURFACE POSITION
surfacePositionLat = num2str(pFloatDetails.cycle(9), '%3.2f');
surfacePositionLon = num2str(pFloatDetails.cycle(10), '%3.2f');
% CYCLE PARAMETER
floatCycleStartTime = [pFloatDetails.cycle(4:8), 0]; % seconds always zero
floatCycleStartTimeRafosDays = num2str( ...
artoa.convert.dmy2rd(floatCycleStartTime(3), floatCycleStartTime(2), floatCycleStartTime(1)) ...
+ artoa.convert.hms2rd(floatCycleStartTime(4), floatCycleStartTime(5), 0) ...
);
floatCycleStartTime = num2str(floatCycleStartTime);
floatCycleEndTime = [pFloatDetails.cycle(11:15), 0]; % seconds always zero
floatCycleEndTimeRafosDays = num2str( ...
artoa.convert.dmy2rd(floatCycleEndTime(3), floatCycleEndTime(2), floatCycleEndTime(1)) ...
+ artoa.convert.hms2rd(floatCycleEndTime(4), floatCycleEndTime(5), 0) ...
);
floatCycleEndTime = num2str(floatCycleEndTime);
if size(pFloatDetails.offset, 1) > 1
floatOffsetEnd = pFloatDetails.offset(2,end);
else
floatOffsetEnd = NaN;
end
header = { ...
['** Float: ' floatname], ...
['** Variables: InterpFlag LineNum RafosDay Temp Pres Lat Lon U V W'], ...
['** Units : # # # degC dbar deg deg cm/s cm/s mm/s'], ...
['** Dummies : NA NA NA -9.99 -999 999 999 999 999 999'], ...
['** Cycle : ' cycle], ...
['** Launch position (Cycle Start position): ' ...
launchPositionLat ' ' launchPositionLon], ...
['** Surface position (Cycle End position) : ' ...
leprob001
committed
surfacePositionLat ' ' surfacePositionLon], ...
['** Cycle Start time : ' floatCycleStartTime ' (RAFOS day ' floatCycleStartTimeRafosDays ')'], ...
['** Launch time : ' launchTime ' (RAFOS day ' launchTimeRafosDays ')'], ...
['** Cycle End time : ' floatCycleEndTime ' (RAFOS day ' floatCycleEndTimeRafosDays ')'], ...
['** First surface Position time : ' recoverTime ' (RAFOS day ' recoverTimeRafosDays ')'], ...
['** Float clock offset (init/final) : ' num2str(pFloatDetails.offset(1,end)) ' / ' num2str(floatOffsetEnd),' seconds'], ...
leprob001
committed
headerString = strjoin(header, newline);
leprob001
committed
%% COLLECT DATA STRING
for i = 1:size(pData, 1)
dataString = [ ...
dataString ...
sprintf('%12d%12d%12.2f%12.3f%12.1f%12.3f%12.3f%12.2f%12.2f%12.2f\n', pData(i, :)) ...
];
leprob001
committed
%% IF NO TRAJECTORY AVAILABLE
if (nargin == 3)
headerString = [headerString newline ' * No trajectory information, flt not tracked.' newline];
saveToFile(pFilename, headerString, dataString);
success = true;
return;
elseif (~isstruct(pTrajectory))
warning('Trajectory variable is not a struct. It will NOT be used!');
end
leprob001
committed
%% TRAJECTORY IS AVAILABLE
if (pTrajectory.trackParameter.dopplerCorrection == 1)
leprob001
committed
dopplerCorrectionUsed = 'yes';
else
dopplerCorrectionUsed = 'no';
end
leprob001
committed
trajectoryHeader = { ...
['** Tracking method: ' strjoin(pTrajectory.trackParameter.soundsourceCombinations.trackingMethod, ', ')], ...
['** Interpolation method: ' pTrajectory.trackParameter.interpolationMethodString], ...
['** Interpolation step size: ' num2str(pTrajectory.trackParameter.interpolationInterval) ' hours'], ...
['** Interpolation gap size: ' num2str(pTrajectory.trackParameter.gapSize)], ...
leprob001
committed
['** Doppler correction: ' dopplerCorrectionUsed], ...
['** -------'], ...
['** Sound source combinations: (rafos day, sound sources, reference position, sound speed)'] ...
};
trajectoryHeader = strjoin(trajectoryHeader, newline);
soundSourcesHeader = '';
for i = 1:size(pTrajectory.trackParameter.soundsourceCombinations, 1)
currentCombination = pTrajectory.trackParameter.soundsourceCombinations(i, :);
leprob001
committed
soundSourcesHeader = [ ...
soundSourcesHeader ...
'** ' num2str(currentCombination.combinationBegin) ' to ' num2str(currentCombination.combinationEnd) ': ' ...
currentCombination.soundsources ' ' ...
currentCombination.referencePosition ' ' ...
num2str(currentCombination.soundspeed1) ...
leprob001
committed
newline ...
];
end
soundSourcesHeader = [ ...
soundSourcesHeader ...
'** -------' newline ...
'** Additional Float clock offsets, seconds (beginning, end): ' ...
num2str(pTrajectory.offsets{'Float', 'OffsetStart'}) ...
leprob001
committed
' ' ...
num2str(pTrajectory.offsets{'Float', 'OffsetStart'}) newline ...
leprob001
committed
'** -------' newline ...
' * l ----------' ...
];
headerString = strjoin([ ...
leprob001
committed
headerString newline...
trajectoryHeader newline ...
soundSourcesHeader newline ...
leprob001
committed
%% Save to file
saveToFile(pFilename, headerString, dataString);
%% Update return variable
success = true;
leprob001
committed
%% Nested functions
function saveToFile(pFilename, pHeader, pData)
fid = fopen(pFilename, 'w');
fprintf(fid, pHeader);
fprintf(fid, pData);
fclose(fid);
end