function X = readout(FileName)
% READOUT  - Read the ASCII data files created by ASCIICON
%
% Use as: x = readout
%      or x = readout(FileNameString)
%
% Inputs: FileNameString = Name of the *.out file containing data
%         processed by ASCIICON to be read. If not supplied
%         the user will be prompted for input. It is assumed
%         that the *.out file is tab delimited.
%
% Output: x = structure containing the data from the file specified by FileNameString
%         Each column of the original *.out file will be stored as a seperate field in 
%         the structure. Each field will be named from the column headers (ex.
%         LU(555) will become LU_555)
%
% Note: Any values that are equal to -999 are changed to NaN. 

% Brian Schlining
% 11 Jan 1998
% 17 Sep 1999; Bug Fix

%==============
% Get FileName
%==============
if ~nargin 
   
   [infile inpath] = uigetfile('*.out','Select ASCII Eqpac Data File',0,0);
   if infile == 0 
      X = [];
      return
   end
   FileName = [inpath infile];
   
end

% Get filename from the path and store it
[trash, File, Ext] = fileparts(FileName);
X.Filename         = [File Ext];

fid        = fopen(FileName,'rt');    % Open the File 
Header     = fgetl(fid);              % Get the first line which contains the column descriptions
BytesInHeader = length(Header);       % Need to reposition the file pointer

%==========================================================
% Figure out roughly how many rows of data are in the file
%==========================================================
sByte       = ftell(fid);             % Get current position (in bytes)
fseek(fid,0,'eof');                   % go to the end of the file
fByte       = ftell(fid);             % Get the position in Bytes
BytesOfData = fByte - sByte;          
fseek(fid,BytesInHeader + 2,'bof');   % Rewind back to the original position + 1 line

%====================
% Parse apart Header
%====================
% First, get rid of the parenthesis
lp         = findstr('(',Header);
rp         = findstr(')',Header);
if length(lp) ~= length(rp)
   error(['Unmatched parenthesis in the header line of ' infile])
end
Header(lp) = '_';    % left ( is changed to _
Header(rp) = ' ';    % right ) is changed to a space

% After Every column name (except the last one) there is a tab
tabIndices = findstr(setstr(9),Header);   % Find the tabs
numColumns = length(tabIndices) + 1;     % Get the number of columns in the file
tabIndices = [0 tabIndices (length(Header) + 1)]; % A little creative indexing

% Write each column name to a cell, make sure to remove all parenthesis
% or it won't work (ex. Lu(670) -> Lu_670)
for j = 1:(length(tabIndices) - 1)
   
   Start         = tabIndices(j) + 1;
   Finish        = tabIndices(j + 1) - 2;
   
   % Need the columnName for use with SETFIELD used in the loop that reads
   % the data
   columnName{j} = Header(Start:Finish);
   
   % Create the fields need in the data structure
   X             = setfield(X, Header(Start:Finish), []);
   
end

%===============
% Read the data
%===============

% Locate the column with the time
timeColumn = strcmp('TIME_TAG',columnName);
Row = 0;                      % Start the row counter
OK = 1;

fprintf(1,'(READOUT)')
while OK
   
   s = fgetl(fid);            % Get a line of data
   
   while isempty(s)           % Sometime fgetl returns a line feed
      s = fgetl(fid);         % which sets s = [];
   end
   
   Row = Row + 1;             % Advance the row index everytime a new line is read
   
   
   % Pre-allocate memory; For opening larger files most of the time is spent
   % on malloc and memcopy which is very VERY SLOW 
   if Row == 1
      BytesPerRow = length(s);
      numRows  = ceil(BytesOfData/BytesPerRow);
      Dat = ones(numRows, numColumns)*NaN;   
   end
   
   if ~rem(Row,200)
      fprintf(1,'.')
   end
   
   
   if ~isstr(s)               % Break out when the end of the file is reached
      % Axe off any hanging NaN's created by preallocating memory
      j   = find(~isnan(Dat(:,1)));
      Dat = Dat(j,:);
      j   = find(Dat == -999); % Find -999's
      Dat(j) = NaN;            % This line changes -999's to NaN's
      for i = 1:numColumns
         X = setfield(X,{1},char(columnName(i)),Dat(:,i));
      end
      fprintf(1,'\n')
      fclose(fid);
      return
   end
   
   % Not every line is the same length, so find out where each data value
   % starts and stops by finding the tabs
   tabIndices = [0 findstr(setstr(9),s) (length(s) + 1)];
   
   % This is SLOW, but we need to loop through each value in the line in order
   % to catch the TIME_TAG column
   for i = 1:numColumns
      
      % Data values will be located between each tabIndices
      Start  = tabIndices(i) + 1;
      Finish = tabIndices(i + 1) - 1;  
      
      % if its the time column, it needs to be parsed apart carefully.
      % Here it's converted to Matlabs' serial date number format.
      if timeColumn(i)
         
         DateString        = s(Start:Finish);
         if length(DateString) < 18
            Year              = sscanf(DateString(1:2),'%f');
            if Year < 95         % Y2K rears its ugly head, I kick it here.
               Year = Year + 2000;
            elseif Year >= 95 & Year < 100
               Year = Year + 1900;
            end
            Month             = sscanf(DateString(4:5),'%f');
            Day               = sscanf(DateString(7:8),'%f');
            Hour              = sscanf(DateString(10:11),'%f');
            Minute            = sscanf(DateString(13:14),'%f');
            Second            = sscanf(DateString(16:17),'%f');
            Dat(Row,i) = datenum(Year, Month, Day, Hour, Minute, Second);
         else
            Year              = sscanf(DateString(1:4),'%f');
            Month             = sscanf(DateString(6:7),'%f');
            Day               = sscanf(DateString(9:10),'%f');
            Hour              = sscanf(DateString(12:13),'%f');
            Minute            = sscanf(DateString(15:16),'%f');
            Second            = sscanf(DateString(18:19),'%f');
            Dat(Row,i) = datenum(Year, Month, Day, Hour, Minute, Second);

         end
         
         
         
      else
         Dat(Row,i) = sscanf(s(Start:Finish),'%f');
         % The method commnted out here takes 5 times longer than the method
         % now implemented.
         % Dat = sscanf(s(Start:Finish),'%f');
         %X   = setfield(X,{1},char(columnName(i)),{Row,1},Dat);
         
      end
      
      
      
   end
   
   
   
end













