function [ctd,varlabel,names,sensors]=ctd_rd(cnv_file,FMT);
% CTD_RD Reads the SeaBird ASCII .CNV file format
%
%  Usage:   CTD=ctd_rd(cnv_file);
%
%     Input:  cnv_file = name of .CNV file  (e.g. 'cast002.cnv')
%
%     Output: CTD - a data structure containing the CTD data and header info.
%
%  There are various formats possible for time/location information.
%  Some of these can be handled with an optional second input parameter:
%           CTD=ctd_rd(cnv_file,FORMAT)
%
%  where FORMAT = 'NMEA'  for SEASAVE output with GPS included through deckbox
%
%                          * System UpLoad Time = Oct 10 1999  18:20:32
%                          * NMEA Latitude = 48 36.69 N
%                          * NMEA Longitude = 123 13.07 W
%                          * NMEA UTC (Time) = Oct 10 1999  18:20:32
%
%                 'IR'    for an internally recording mode with a hand-typed
%                         header in this form:
%                         
%                          ** Latitude = 49 21.092 N
%                          ** Longitude = 121 49.028 W
%                          ** PST (Time) =Nov 23 2000 07:45
%
%                         will also work with SEASAVE output if no
%                         GPS NMEA string available.
%                         (default mode)
%
%                         If no '** Time' line gets it from System Upload Time
%
%                 'RP'    Ignore any header data but decode System Upload Time for
%                         the year, and the 'cast' line (DH command) for time -
%                         good for IR mode when to-yo-ing or otherwise too lazy
%                         to create proper headers.
%
%                 'LAB'   for a mode with no NMEA or header data (i.e. lab
%                         testing)
%
%  Add more lat,lon and date string handling if your .CNV files are different.
%

%  4-8-98  Rich Signell (rsignell@usgs.gov)  
%     incorporates ideas from code by Derek Fong & Peter Brickley
%  19-9-99 R. pawlowicz (ric@ocgy.ubc.ca)
%      - added a lot more decoding plus the idea of a data stucture for output
%  12-6-00 Changes variable names slightly.
%  19-2-02 dms as well as dmm.mm formats
%  20-5-11 modified by Rowan Fox (ro1@uvic.ca), adding in model #, temp
%  sensor SN # & cond sensor SN
%  16-5-12 can now read new-format cnv files with xml info


if nargin==1,
 FMT='IR';
end;

ctd.name='ctd';
ctd.station='';

% Open the .cnv file as read-only text

if isempty(findstr(lower(cnv_file),'.cnv')),
  cnv_file=[cnv_file '.cnv'];
end;
  
fid=fopen(cnv_file,'r');

% Read the header.
lat=[];
lon=[];
gtime=NaN(1,6);
tzone='unknown';
% Stop at line that starts with '*END*'

str='*START*';
while (~strncmp(str,'*END*',5));
  
  str=fgetl(fid);

   switch FMT
     case 'NMEA'
	 if (strncmp(str,'* NMEA Lat',10))
            lat=get_lat(str);
	 elseif (strncmp(str,'* NMEA Lon',10))
            lon=get_lon(str);
	 elseif (strncmp(str,'* NMEA UTC',10))
           gtime=get_timestamp(str);
	   tzone='UTC';
	end;

     case 'IR',

	 if any(findstr(str,'Latitude')) | any(findstr(str,'Lat'))
            lat=get_lat(str);
	 elseif any(findstr(str,'Longitude')) | any(findstr(str,'Long'))
            lon=get_lon(str);
	    
   %    Read the  TIME string.  This may vary with CTD setup. Will need
   %      ** xxxxxxxxxxTimexxxx = 21 Dec 2005 hh:mm:ss
   %     where timezone may also be in there somewhere.
   
        elseif strncmp(str,'**',2) & any(findstr(str,'Time')),
           gtime=get_timestamp(str);
	   tzone='unknown';
	   if any(findstr(str,'PST')),
	     tzone='PST';
	   elseif any(findstr(str,'PDT')),
	     tzone='PDT';
	   elseif any(findstr(str,'UTC')),
	     tzone='UTC';
	   elseif any(findstr(str,'EST')),
	     tzone='EST';
	   elseif any(findstr(str,'EDT')),
	     tzone='EDT';
	   end;  
   % The default - get a time from the 'upload' string (usually the other time
   % strings are later in the file so they will overwrite this, if they exist).	
	elseif (strncmp(str,'* System UpLoad',15)),
           tzone='unknown';
           gtime=get_timestamp(str);
	end;	

       case 'LAB',  	
       
  
        if (strncmp(str,'* System UpLoad',15)),
           tzone='unknown';
           gtime=get_timestamp(str);
	end;
	
      case 'RP',  
      	

	if (strncmp(str,'* System UpLoad',15))
           is=findstr(str,'=');
	%EXTRACT THE UPLOAD YEAR FOR CAST START TIME Roger 2003sep04
           upyearstr=str(is+9:is+12);
	end;

   
   %-------------------------------------------------------------------
	% READ CAST START TIME, SAMPLE RATE, COMPUTE mtime Roger 2003sep04
	% * cast 0  06/23  17:38:06   samples 0 to 1334 sample rate = 1 scan every 0.5 seconds
	if (strncmp(str,'* cast ',7))
           %Find slash
           indslash=find(str=='/');
           indcolon=find(str==':');

	   if length(indslash)==1 & length(indcolon)>=2
             datstr=[upyearstr ' '...
                     str(indslash-2:indslash-1) ' ' ...
                     str(indslash+1:indslash+2) ' ' ...
                     str(indcolon(1)-2:indcolon(1)-1) ' '...
                     str(indcolon(1)+1:indcolon(2)-1) ' '...
                     str(indcolon(2)+1:indcolon(2)+2)];
             mtime=datenum(str2num(datstr));
	     gtime=datevec(mtime);
             fprintf('Date from CAST START TIME in timezone of SBE clock\n');
	   else
              error('ERROR: CAST START TIME: str does not have expected form')
	   end;

	end

   %
      otherwise,
	error('Unrecognized format specifier');
    end;
  	
%-----------------------------
%
% Read the station name from a comment line
%
     if (strncmp(lower(str),'** station',10)),
        ctd.station=fliplr(deblank(fliplr(deblank(str(min(findstr(str,':'))+2:end)))));
%-----------------------------
%
% Read the ctd model from a comment line
%
     elseif (strncmp(str,'* Sea-Bird',10)),
        ctd.model=str(findstr(str,'Sea-Bird SBE ')+13:findstr(str,' Data File')-1);
%-----------------------------
%
% Read the ctd temperature sensor SN from a comment line
%
     elseif (strncmp(str,'* Temperature SN = ',19)),
        ctd.tempsn=str(findstr(str,'* Temperature SN = ')+19:end);
%-----------------------------
%
% Read the ctd conductivity sensor SN from a comment line
%
     elseif (strncmp(str,'* Conductivity SN = ',20)),
        ctd.condsn=str(findstr(str,'* Conductivity SN = ')+20:end);
        
%-----------------------------
%
% Read the depth from a comment line
%
     elseif (strncmp(lower(str),'** depth',8)),
        idelim=findstr(str,':');
        ctd.depth=sscanf(str(idelim+1:end),'%f');
	if isempty(ctd.depth), ctd.depth=NaN; end;
	% Units?
	strrem=str(idelim+1:end);strrem(strrem>=48 & strrem<=57)=' ';
	if any(findstr(str(idelim+1:end),' m')),
	   % OK
	elseif any(findstr(str(idelim+1:end),' ft')) ,
	   ctd.depth=ctd.depth*0.3048;
	end;    

%------------------------------
%
% Get sampling interval
%
     elseif (strncmp(str,'# interval',10)),
        ctd.samp_interval=sscanf(str(findstr(str,':')+1:end),'%f');

%------------------------------
%
% Get start time  
%
     elseif (strncmp(str,'# start_time',12)),
        ctd.start_time=str(15:end);
        ctd.start_mtime=datenum(str(15:end),'mmm dd yyyy HH:MM:SS');
	
%------------------------------
%
%    Read the variable names & units into a cell array
%
     elseif (strncmp(str,'# name',6))  
        var=sscanf(str(7:10),'%d',1);
	var=var+1;
        ctd.varlabel{var}=str(findstr(str,'=')+2:min([findstr(str,':')-1 ...
                              findstr(str,'/')-1 findstr(str,'-')-1]));
%------------------------------
%
%    Read the sensor names into a cell array
%
     elseif (strncmp(str,'# sensor',8))  
        sens=sscanf(str(10:11),'%d',1);
        sensors{sens+1}=str;
%------------------------------
%
%    Read the sensor ranges into a cell array
%
     elseif (strncmp(str,'# span',6))  
        sens=sscanf(str(8:9),'%d',1);
        ctd.spans{sens+1}=sscanf(str(findstr(str,'=')+1:end),'%f,%f');
%
%  pick up bad flag value
     elseif (strncmp(str,'# bad_flag',10))  
        isub=13:length(str);
        bad_flag=sscanf(str(isub),'%g',1);
     end
end
%==============================================


%  Done reading header.  Now read the data!

nvars=var;  %number of variables

% Read the data into one big matrix

data=fscanf(fid,'%f',[nvars inf]).';
fclose(fid);


% Flag bad values with NaN

data(data==bad_flag)=NaN;

if exist('sensors'), ctd.sensors=char(sensors); end;

ctd.latitude=lat;
ctd.longitude=lon;
ctd.gtime=gtime;
ctd.mtime=datenum(gtime(1),gtime(2),gtime(3),gtime(4),gtime(5),gtime(6));
ctd.tzone=tzone;

if strcmp(FMT,'RP'),
  ctd.mtimescan=[0:size(data,1)-1]*ctd.samp_interval/86400+mtime;
end;  

labeldel=[];
for k=1:length(ctd.varlabel),
  if diff(ctd.spans{k})~=0,
    eval(['ctd.' ctd.varlabel{k} '=data(:,k);']);
  else
    labeldel=[labeldel k];
  end;
end;
ctd.varlabel(labeldel)=[];
ctd.spans(labeldel)=[];
 
return

%---------------------------------------------------
function lon=get_lon(str);
% decodes latitude from input string

% Get delimiter - '=' or ':'
is=findstr(str,'=');
if isempty(is), is=findstr(str,':'); end;


isub=is+1:length(str);
dm=sscanf(str(isub),'%f');

% E or W
if(findstr(str(isub),'E')); sigl=1; else sigl=-1; end;

% dd.ddd or dd mm.mmm or dd mm ss formats
switch (length(dm)),
case 1,
   lon=sigl*dm;
case 2,   	
   lon=sigl*(dm(1)+dm(2)/60);
case 3,  
   lon=sigl*(dm(1)+dm(2)/60+dm(3)/3600);
otherwise,
   lon=NaN;
   disp(['Can''t scan string ->' str '<- for longitude']);    
end
 
return;

%---------------------------------------------------
function lat=get_lat(str);
% decodes latitude from input string

% Get delimiter - '=' or ':'
is=findstr(str,'=');
if isempty(is), is=findstr(str,':'); end;


isub=is+1:length(str);
dm=sscanf(str(isub),'%f');

% N or S
if(findstr(str(isub),'N')); sigl=1; else sigl=-1; end;

% dd.ddd or dd mm.mmm or dd mm ss formats
switch (length(dm)),
case 1,
   lat=sigl*dm;
case 2,   	
   lat=sigl*(dm(1)+dm(2)/60);
case 3,  
   lat=sigl*(dm(1)+dm(2)/60+dm(3)/3600);
otherwise,
   lat=NaN;
   disp(['Can''t scan string ->' str '<- for longitude']);    
end
 
return;
%--------------------------------------------------
function gtime=get_timestamp(str);
% Decodes time string

% Time to right of '='
idelim=findstr(str,'=');
if any(idelim),
   str=str(idelim+1:end);
else   % try a colon delimiter
 idelim=findstr(str,':');
 if any(idelim),
    str=str(idelim(1)+1:end);
 end;
end;
     
% is there hh:mm:ss in there?
is=findstr(str,':');
if any(is),
  isub=is(1)-2:length(str);
  
  % Date in   Dec 21 2005 HH:MM format
  nbl=find(str(1:is(1)-3)~=' ');
  datstr=str(min(nbl):max(nbl));
  ibl=findstr(datstr,' ');
  if length(ibl)==2,
    % Write into 21-Dec-2001 format which matlab can decode
    datstr=[datstr(ibl(1)+1:ibl(2)-1) '-' datstr(1:ibl(1)-1) '-' datstr(ibl(2)+1:end)];
    if ibl(2)-ibl(1)==2,
      datstr=['0' datstr];
    end; 
    gtime=datevec(datstr);
    % Add hh:mm:ss
    if length(is)==1,
      gtime([4:5])=sscanf(str(isub),'%d:%2d');
    elseif length(is)==2,
      gtime([4:6])=sscanf(str(isub),'%d:%2d:%2d');
    else
      disp(['Can''t scan string ->' str '<- for time of day']);    
      gtime=[0 0 0 0 0 0];
    end; 
  else
    disp(['Can''t scan string ->' str '<- for day of year']);    
   gtime=[0 0 0 0 0 0];
  end; 
else
    disp(['Can''t scan string ->' str '<- for time of day']);    
   gtime=[0 0 0 0 0 0];
end; 




