
% 
% Level_0 (L0) -> Level_1 (L1) conversion
% 
% Loads the MVP data from the .raw files and writes them into a .mat file 
% with the same name. The .mat file contains three structures:
% - metadata (fileIndex, shipLog, lon, lat, date)
% - info (instrType, fSampl)
% - data (pres, temp, cond, psal, LOPCcounts, analogOutput - if uCTD
%         pres, temp, soundVel, LOPCcounts, analogOutput - if SVPT)
% 
% The only data processing from the .raw to the .mat is the following:
% - ADC counts are transformed into analog output (voltage), since the
%   conversion depends only on hardware parameters
% - LOPC counts are actually logged as counts/0.5s (cf. MVP MSFFF LOPC 
%   Integration Guide, p. 15), so they are simply transformed into counts/s
% 
% 
% N.B.: The configuration can either be small fish (only SVPT) or big fish 
%       (LOPC, uCTD, fluo), with the AML uCTD or with the SVPT sensor.
%       Nevertheless, this script is parametrized with the OUTPACE settings
%       (sampling frequency, column names in the .raw files) in the 
%       Specific Parameters section, so if it needs to be adapted to 
%       different configurations care must be taken.
% 
% 
% v0
%   Lucio Bellomo, 23 June 2015
% 


clear all; clc;


%% Parameters to be set by the user
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Folder where the .raw files are
pathL0 = '/media/NeNe/DatiVari/AtalanteDisk/OUTPACE_MVP/MVP_DATA/All_Data/L0/';

% Folder where the .mat files are to be written
pathL1 = '/media/NeNe/DatiVari/AtalanteDisk/OUTPACE_MVP/MVP_DATA/All_Data/L1/';

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%% Specific parameters
% Sampling frequency of the CTD (Hz)
fSampl_uCTD = 1;     % it was set to 1 Hz by mistake by OSIL after the calibration!!!
fSampl_SVPT = 16;

% Variables associated to the .raw columns
columnNames_uCTD = {'pres','cond', 'temp','psal',  'ADCcounts','LOPCcounts'};
columnUnits_uCTD = {'dbar','mS/cm','degC','PSS-78','',         'cnts/0.5s'};
columnNames_SVPT = {'pres','soundVel','temp','ADCcounts','LOPCcounts'};
columnUnits_SVPT = {'dbar','m/s',     'degC','',         'cnts/0.5s'};

% Data format in the .raw file
dataFormat_uCTD = '%f  %f  %f %f  %f %f';
dataFormat_SVPT = '%f  %f  %f  %f %f';


%% Read the transect filenames
fileNames = dir([pathL0 filesep '*.raw']);
nProf = length(fileNames);


%% Work profile by profile
hWait = waitbar(0,'Processing .raw files...');
for iProf = 1 : nProf
    
    % Read the file
    fileName = [pathL0 filesep fileNames(iProf).name];
    metadata.fileName = fileNames(iProf).name(1:end-4);
    
    
    % Open the file
    fid = fopen(fileName,'rt');
    format long;
    
    
    % Read the header
    hdr = [];
    ln  = [];
    while ~feof(fid) && isempty(strfind(ln,'<END_OF_HEADER>'))
        ln = fgets(fid);
        hdr = [hdr ln];
    end
    
    % - profile index
    iind = strfind(hdr,'Index:');
    if ~isempty(iind)
        metadata.profileIndex = sscanf(hdr(iind:end),'Index: %d');
    else
        disp('Wrong format for File Index!');
    end
    
    % - ship's log
    ilog = strfind(hdr,'Ship''s Log (kt):');
    if ~isempty(ilog)
        metadata.shipLog.value = sscanf(hdr(ilog:end),'Ship''s Log (kt): %f');
        metadata.shipLog.unit  = 'kt';
    else
        disp('Wrong format for Ship''s log!');
    end
    
    % - longitude
    ilon = strfind(hdr,'LON (dddmm.mmmmmmm,E):');
    if ~isempty(ilon)
        lon = sscanf(hdr(ilon:end),'LON (dddmm.mmmmmmm,E): %f,%s[\n]');
        EW  = char(lon(2));
        lon = lon(1);
        lon = lonlat_NMEA_to_dec(lon);  % Convert into degrees.decimal instead of degres minutes.decimal
        if strcmp(EW,'W')
            lon = 360-lon;
        end
        metadata.lon.value = lon;
        metadata.lon.unit  = 'degE';
    else
        disp('Wrong format for Longitude!');
    end
    
    % - latitude
    ilat = strfind(hdr,'LAT ( ddmm.mmmmmmm,N):');
    if ~isempty(ilat)
        lat = sscanf(hdr(ilat:end),'LAT ( ddmm.mmmmmmm,N): %f,%s[\n]');
        NS  = char(lat(2));
        lat = lat(1);
        lat = lonlat_NMEA_to_dec(lat);  % Convert into degrees.decimal instead of degres minutes.decimal
        if strcmp(NS,'S')
            lat = -lat;
        end
        metadata.lat.value = lat;
        metadata.lat.unit  = 'degN';
    else
        disp('Wrong format for Latitude!');
    end
       
    % - time & date
    itime = strfind(hdr, 'Time (hh|mm|ss.s):');
    if ~isempty(itime)
        time = sscanf(hdr(itime:end),'Time (hh|mm|ss.s): %d:%d:%f');
    else
        disp('Wrong format for Time!');
    end
    idate = strfind(hdr, 'Date (dd/mm/yyyy):');
    if ~isempty(itime)
        date = sscanf(hdr(idate:end),'Date (dd/mm/yyyy): %d/%d/%d');
    else
        disp('Wrong format for Date!');
    end
    date_vec = datestr([date(3) date(2) date(1) time(1) time(2) time(3)]);
    
    metadata.date.value = datenum(date_vec);   % days since 01-Jan-0000 00:00:00
    metadata.date.unit  = 'days since 01-Jan-0000 00:00:00';
    
    % - instrument type (uCTD or SVPT)
    iinstr = strfind(hdr, 'SER1 Type:');
    if ~isempty(iinstr)
        instr = sscanf(hdr(iinstr:end),'SER1 Type: %d,%s');
        instr = char(instr(2:end)');
    else
        disp('Wrong format for Instrument type!');
    end
    if strcmp(instr,'LOPC+uCTD')
        uCTD_or_SVPT = 1;
    elseif strcmp(instr,'LOPC+uSVP')
        uCTD_or_SVPT = 2;
    else
        error('The instrument type is not valid!');
    end
    if uCTD_or_SVPT == 1
        fSampl      = fSampl_uCTD;
        columnNames = columnNames_uCTD;
        columnUnits = columnUnits_uCTD;
        dataFormat  = dataFormat_uCTD;
        instrType   = 'uCTD+fluo';
    else
        fSampl      = fSampl_SVPT;
        columnNames = columnNames_SVPT;
        columnUnits = columnUnits_SVPT;
        dataFormat  = dataFormat_SVPT;
        instrType   = 'SVPT+fluo';
    end
    
    % - read the data
    while ~feof(fid) && isempty(deblank(ln))    % empty lines
        ln = fgets(fid);
    end
    if ~feof(fid)
        rawData = double(fscanf(fid,dataFormat,[length(columnNames) inf]))';
    else
        rawData = [];
    end
    
    
    % Build the variables
    if isempty(rawData)     % if a file doesn't have any data, just skip it
        data = [];
    else
        for iVar = 1 : length(columnNames)
            if strcmp(columnNames{iVar},'ADCcounts')
                % - conversion from ADC counts to analog voltage
                name              = 'analogOutput';
                data.(name).value = rawData(:,iVar) * 5 / 2^12;
                data.(name).unit  = 'V';
            elseif strcmp(columnNames{iVar},'LOPCcounts')
                % - counts/0.5s -> counts/s (cf. MVP MSFFF LOPC Integration Guide, p. 15)
                name              = columnNames{iVar};
                data.(name).value = rawData(:,iVar) * 2;
                data.(name).unit  = 'counts/s';
            else
                name              = columnNames{iVar};
                data.(name).value = rawData(:,iVar);
                data.(name).unit  = columnUnits{iVar};
            end
        end
    end
    
    
    % Build the parameter structure
    params.instrType = instrType;
    params.fSampl.value = fSampl;
    params.fSampl.unit  = 'Hz';
    
    
    % Close the file
    fclose(fid);
    
    
    % Save the transect data into a .mat file
    [~, matFileName, ~] = fileparts(fileName);
    save([pathL1 filesep matFileName],'params','metadata','data');
    
    
    % Clear the structures
    clear params metadata data
    
    
    % Waitbar
    waitbar(iProf/nProf);
end
close(hWait);


%% Log message
disp(blanks(1)');
disp(['*** Done - ' num2str(nProf) ' .mat files created ***']);
disp(blanks(1)');
