Skip to content
Snippets Groups Projects
csv2btl.m 12 KiB
Newer Older
function csv2btl
% Programme de lecture des fichiers bouteilles au format CSV
% et conversion au format des fichiers BTL du programme TSG-QC
%
% ------------------------------------------------------------

% Repertoire courant par default
% ------------------------------
repIn = '.';
repOut = repIn;

% Constantes
% ----------
DELIMITER = ';';  % Chaque colonne du fichier est separee par DELIMITER
NBELEMENT = 6;    % Nombre d'lment de chaque ligne du fichier en entree

% define configuration file name as csv2btl.ini
% ---------------------------------------------
file_ini = strcat(mfilename,'.ini');
fid_ini = fopen(file_ini, 'r');

% if file exist, read it
% ----------------------
if (fid_ini ~= -1)
    
    % display information on command window
    % --------------------------------------
    fprintf('\nreading %s ...\n', file_ini);
    % test the end-of-file
    % --------------------
        % read next line
        % --------------
        inputText = textscan(fid_ini, '%s', 1, 'delimiter', '\n');
        
        for ii = {'repIn', 'repOut'}
            
            % get key, use char because i is cell
            % -----------------------------------
            clef = char(ii);
            
            % use string instead cell
            % -----------------------
            str = inputText{1}{1};
            regex = strcat('^\s*', clef, '\s*=\s*["]*(.+?)["]*$');
            match = regexp( str, regex, 'tokens');
            
            
            % build tsg struct
            % ----------------
            if ~isempty(match)
                cfg.(clef) = match{1}{1};
                
                % for debbuging only
                % ------------------
                fprintf('%s -> %s\n', clef, cfg.(clef));
                continue
            end
    % close .ini file
    % ---------------
    fclose(fid_ini);
else
    fprintf('Warning: can''t find configuration file %s\n', file_ini);
    fprintf('Using current directory as output\n');
    cfg.repIn = pwd;
    cfg.repOut = pwd;
% Ouverture du fichier CSV
% ------------------------
[file, pathname, filterIndex] = uigetfile( {'*.csv'}, 'Pick a file');

if ~isequal(file, 0)
    % -----------------------------
    fileIn  = fullfile(pathname, file);
    file    = strrep(file, '.csv', '.btl');
    fileOut = fullfile(cfg.repOut, file);
    fprintf('\ninput file: %s\n', fileIn);
    fprintf('ouput file: %s\n', fileOut);
    % Parametres en sortie vides
    % --------------------------
    nblig = 0;
    DataIn = [];
    % Le nombre d'elements de l'entete determine le nombre de chaine a lire.
    % Je cree ici la chaine de caractere decrivant le format utilise par
    % textscan
    % ----------------------------------------------------------------------
    theFormat = repmat(' %s', 1, NBELEMENT);
    % Ouverture du fichier en lecture '.CSV'
    % --------------------------------------
    fid = fopen( fileIn, 'r');
    % Teste si le fichier existe
    % --------------------------
    if fid ~= -1
        
        % Read the first 8 (3) lines
        % ----------------------
        for i = 1:8
            line = fgetl( fid );
        
        % Lecture de la date d'analyse des bouteilles
        % -------------------------------------------
        C = textscan(line, '%*s %s %*s %*s %d/%d/%d', 4,'delimiter', DELIMITER);
        cruiseID = char(C{1});
        year  = double( C{4} );
        day = double( C{3} );
        month   = double( C{2} );
        
        % conversion au format du logiciel TSGQC
        % -------------------------------------
        dateAnalysis = datestr( datenum(year,month,day,0,0,0), 'yyyymmddHHMMSS'  );
        
        % Lecture du type de bouteilles
        % -----------------------------
        line = fgetl( fid );
        C = textscan(line,'%*s%s', 1,'delimiter', DELIMITER)';
        bottleType = char(C{1});
        
        % Skip 4 lines
        % ------------
        for i = 1:4
            line = fgetl( fid );
        
        % Lecture des donnes
        %
        % textscan permet de lire a peu pres tout, memes les lignes
        % incompletes, plus courtes.
        % Par contre les donnes lues sont enregistrees dans une
        % Cellule de cellule
        % ATTENTION :
        %   dans le cas de lignes incompletes textscan n'utilise pas
        %   enptyValue mais une chaine de caracteres vide
        % -----------------------------------------------------------
        data = textscan(fid, theFormat, 'delimiter', DELIMITER,...
            'headerLines', 0 ,...
            'treatAsEmpty', ' ',...
            'emptyValue', NaN);
        
        % Allocation de mmoire
        % ---------------------
        [m,n]   = size(data{1});
        latitude  = NaN*ones(m,1);
        longitude = NaN*ones(m,1);
        year      = NaN*ones(m,1);
        month     = NaN*ones(m,1);
        day       = NaN*ones(m,1);
        hour      = NaN*ones(m,1);
        min       = NaN*ones(m,1);
        sss_buck  = NaN*ones(m,1);
        
        % Decode la date
        % Attention a la position des mois et du jour. Il y a inversion
        % dans les fichiers de Denis entre 2006 2007
        % --------------
        for i = 1 : m
            tab = sscanf( char( data{2}(i)), '%d/%d/%d' );
            if ~isempty( tab )
                year(i)  = tab(3);
                month(i) = tab(1);
                day(i)   = tab(2);
            end
        end
        
        % Decode l'heure
        % --------------
        for i = 1 : m
            tab = sscanf( char( data{3}(i)), '%d:%d' );
            if ~isempty( tab )
                hour(i) = tab(1);
                min(i)  = tab(2);
            end
        end
        
        % Decode les latitudes
        % --------------------
        for i = 1 : m
            [tab, count, errmsg, nextindex] = sscanf( char( data{4}(i)), '%d%d''%s' ); % Avec minutes
            if ~isempty( errmsg )
                tab = sscanf( char( data{4}(i)), '%d%d %s' ); % sans minutes
            end
            if ~isempty( tab )
                latitude(i) = tab(1) + tab(2)/60;
                if strcmp( char(tab(3)), 'S' )
                    latitude(i) = -latitude(i);
                end
            else
                latitude(i) = NaN;
            end
        end
        
        % Decode les longitudes
        % --------------------
        for i = 1 : m
            [tab, count, errmsg, nextindex] = sscanf( char( data{5}(i)), '%d%d''%s' ); % Avec minutes
            if ~isempty( errmsg )
                tab = sscanf( char( data{5}(i)), '%d%d %s' ); % sans minutes
            end
            if ~isempty( tab )
                longitude(i) = tab(1) + tab(2)/60;
                if strcmp( char(tab(3)), 'W' )
                    longitude(i) = -longitude(i);
                end
            else
                longitude(i) = NaN;
            end
        end
        
        % Decode la salinite
        % ------------------
        for i = 1 : m
            tab = sscanf( char( data{6}(i)), '%f' );
            if ~isempty( tab )
                sss_buck(i) = tab(1);
            end
        end
        
        % Fermeture du fichier en lecture
        % -------------------------------
        fclose( fid );
        
        % Ecriture resultat
        % ----------------
        
        % Test si l'un des lments de la date est  NaN
        % ----------------------------------------------
        ind = find(isnan(year) | isnan(month) | isnan(day) | isnan(hour) | isnan(min) );
        if ~isempty( ind )
            
            hmb = msgbox( [{'Date incomplte pour certains enregistrements.'} {' '} ...
                {'Ces enregistrements sont limins.'} {' '} ...
                {'Liste des enregistrements dans le fentre Matlab.'}],...
                'Dcodage Date', 'warn', 'modal');
            
            disp( 'Warning Date' );
            disp( 'Date incomplte pour les enregistrements suivants' );
            disp(ind);
            
            uiwait( hmb );
            
            year(ind)      = [];
            month(ind)     = [];
            day(ind)       = [];
            hour(ind)      = [];
            min(ind)       = [];
            latitude(ind)  = [];
            longitude(ind) = [];
            sss_buck(ind)  = [];
        end
        
        % Test si l'un des lments de la position est  NaN
        % --------------------------------------------------
        ind = find( isnan(latitude) | isnan(longitude) );
        if ~isempty( ind )
            
            msgbox( [{'Position incomplte pour certains enregistrements.'} {' '} ...
                {'Liste des enregistrements dans le fentre Matlab.'}],...
                'Dcodage Position', 'warn', 'modal');
            
            disp( 'Warning Position' );
            disp( 'Position incomplte pour les enregistrements suivants' );
            disp(ind);
        end
        
        % Classement par date croissante
        % ------------------------------
        date = datenum(year, month, day, hour, min, 0 );
        [date, iOrder] = sort(date);
        year      = year(iOrder);
        month     = month(iOrder);
        day       = day(iOrder);
        hour      = hour(iOrder);
        min       = min(iOrder);
        latitude  = latitude(iOrder);
        longitude = longitude(iOrder);
        sss_buck  = sss_buck(iOrder);
        
        % Nombre d'enregistrements
        % ------------------------
        [nbRecords, n] = size(sss_buck);
        
        % Type de donnees : format NetCdf de tsgqc
        % Blank before and after WS, more readable after concatenation
        % ------------------------------------------------------------
        label     = ' WS ';
        sss_type  = label( ones(nbRecords,1), :);
        
        % Cree le tableau donnant la date d'analyse.
        % il faut une date par echantillon
        % ------------------------------------------
        dateAnalysis  = dateAnalysis( ones(nbRecords,1), :);
        
        % tableau des secondes - N'existe pas pour l'instant dans les feuilles
        % Excel
        % --------------------------------------------------------------------
        sec       = zeros(nbRecords,1);
        
        % Code d equlaite des mesures - tout a 0
        % --------------------------------------
        code      = zeros(size(sss_buck));
        
        % Cree un tableau de caracteres avec toutes les informations
        % ----------------------------------------------------------
        bucket = [year month day hour min sec latitude longitude sss_buck code];
        theFormat = '%04d %02d %02d %02d %02d %02d %12.7f %12.7f %6.3f %d';
            bucketStr(i, :) = sprintf( theFormat, bucket(i,:) );
        end
        
        % Concatene le type et la date d'analyse
        % --------------------------------------
        bucketStr = [ bucketStr sss_type ];
        bucketStr = [ bucketStr dateAnalysis ];
        
        % Ouverture du fichier en sortie
        % ------------------------------
        fout = fopen( fileOut, 'w');
        
        if fout ~= -1
            fprintf( fout, '%%CruiseID %s\n', cruiseID );
            fprintf( fout, '%%WS_TYPE %s\n', bottleType );
            fprintf( fout, '%%HEADER YEAR MNTH DAYX hh mi ss LATX_EXT LONX_EXT SSPS_EXT SSPS_EXT_QC SSPS_EXT_TYPE SSPS_EXT_ANALDATE\n');
            if ~isempty(bucketStr)
                for i = 1:nbRecords
                    fprintf(fout, '%s\n', bucketStr(i,:)');
                end
            end
            fclose( fout );
            display( 'End of program ...' );
        else
            fprintf('Opening error : %s\n', fileOut);