function uffin_data(pathname,filename)
%
%  Name: uffin_data.m
% 
%  Usage: uffin_data(pathname,filename)
% 
%  Description:
%    Imports the contents of a universal file containing Type
%    58 data into the appropriate fields in the global variable
%    DATA{1}
%

%  Version SWD970916
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This matlab source code was originally     %
% developed as part of "DIAMOND" at          %
% Los Alamos National Laboratory. It may     %
% be copied, modified, and distributed in    %
% any form, provided:                        %
%  a) This notice accompanies the files and  %
%     appears near the top of all source     %
%     code files.                            %
%  b) No payment or commercial services are  %
%     received in exchange for the code.     %
%                                            %
% Original copyright is reserved by the      %
% Regents of the University of California,   %
% in addition to Scott W. Doebling, Phillip  %
% J. Cornwell, Erik G. Straser, and Charles  %
% R. Farrar.                                 %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%

global DATA

DATA{1} = [];

nc = 0;

%  Open the file

fid = fopen([pathname,filename],'r');

%  Load Measurement Data

eof = 0;

while ~eof
   
   found1 = 0;
   
   % Scan until you find a -1
   
   while ~found1,
      temp = sscanf(fgetl(fid),'%e',1);
      if ~isempty(temp),
         if temp == -1, found1 = 1; end
      end
      if feof(fid), break, end
   end
   
   if feof(fid), break, end
   
   % Check the record type -- if it is not 58, then skip remainder of while loop
   
   if sscanf(fgetl(fid),'%i',1) == 58  % MEASUREMENT DATA TYPE
      
      %   Records 1 thru 5: Comments
      
      nc = nc + 1;
      for i = 1:5,
         temp = fgetl(fid);
         DATA{1}.comment{nc}(i,1:length(temp)) = temp;
      end
      
      %   RECORD 6: DOF Identification
      %   Read function type, Function ID number, Sequence number, Load case ID number,
      %   Response Entity name, Response Node, Response Direction, Ref Entity Name, Ref Node
      %   and Ref Direction
      
      temp = fgetl(fid);
      
      [temp2,t1,t2,cn] = sscanf(temp,'%i',4);
      funtype = temp2(1);
      funid =  temp2(2);
      seqnum =  temp2(3);
      loadid =  temp2(4);
      
      [temp2,t1,t2,co] = sscanf(temp(cn:end),'%c',11);
      respname = temp2;
      cn = cn+co;
      
      [temp2,t1,t2,co] = sscanf(temp(cn:end),'%i',2);
      respnode = temp2(1);
      respdir = temp2(2);
      cn = cn+co;
      
      if loadid == 0,
         
         [temp2,t1,t2,co] = sscanf(temp(cn:end),'%c',11);
         refname = temp2;
         cn = cn+co;
         
         [temp2,t1,t2,co] = sscanf(temp(cn:end),'%i',2);
         refnode = temp2(1);
         refdir = temp2(2);
         
      end
      
      %  Record 7: Data Form
      %  Ordinate data type, number of data values (or pairs for uneven spacing), spacing flag,
      %  abscissa min, abscissa incr, z-axis value
      
      temp = fgetl(fid);
      
      [temp2,t1,t2,cn] = sscanf(temp,'%i',3);
      ordtype = temp2(1);
      numpts =  temp2(2);
      abscspac = temp2(3);
      
      [temp2,t1,t2,co] = sscanf(temp(cn:end),'%e',3);
      abscmin = temp2(1);
      abscincr = temp2(2);
      zvalue = temp2(3);
      
      %  Record 8: Abscissa Data Characteristics
      %  Specific Data Type, Length Units exponent, Force units exponent, temperature units exponent,
      %  Axis label, axis units label
      
      temp = fgetl(fid);
      
      [temp2,t1,t2,cn] = sscanf(temp,'%i',4);
      abscdatatype = temp2(1);
      absclenexp =  temp2(2);
      abscforceexp = temp2(3);
      absctempexp = temp2(4);
      
      [temp2,t1,t2,co] = sscanf(temp(cn:end),'%c',42);
      abscaxislabel = temp2(1:20);
      abscaxisunitslabel = temp2(21:end);
      
      %  Record 9: Ordinate Numerator Data Characteristics
      %  Specific Data Type, Length Units exponent, Force units exponent, temperature units exponent,
      %  Axis label, axis units label
      
      temp = fgetl(fid);
      
      [temp2,t1,t2,cn] = sscanf(temp,'%i',4);
      ordnumdatatype = temp2(1);
      ordnumlenexp =  temp2(2);
      ordnumforceexp = temp2(3);
      ordnumtempexp = temp2(4);
      
      [temp2,t1,t2,co] = sscanf(temp(cn:end),'%c',42);
      ordnumaxislabel = temp2(1:20);
      ordnumaxisunitslabel = temp2(21:end);
      
      %  Record 10: Ordinate Denominator Data Characteristics
      %  Specific Data Type, Length Units exponent, Force units exponent, temperature units exponent,
      %  Axis label, axis units label
      
      temp = fgetl(fid);
      
      [temp2,t1,t2,cn] = sscanf(temp,'%i',4);
      orddendatatype = temp2(1);
      orddenlenexp =  temp2(2);
      orddenforceexp = temp2(3);
      orddentempexp = temp2(4);
      
      [temp2,t1,t2,co] = sscanf(temp(cn:end),'%c',42);
      orddenaxislabel = temp2(1:20);
      orddenaxisunitslabel = temp2(21:end);
      
      %  Record 11: Z Axis Data Characteristics
      %  Specific Data Type, Length Units exponent, Force units exponent, temperature units exponent,
      %  Axis label, axis units label
      
      temp = fgetl(fid);
      
      [temp2,t1,t2,cn] = sscanf(temp,'%i',4);
      zdatatype = temp2(1);
      zlenexp =  temp2(2);
      zforceexp = temp2(3);
      ztempexp = temp2(4);
      
      [temp2,t1,t2,co] = sscanf(temp(cn:end),'%c',42);
      zaxislabel = temp2(1:20);
      zaxisunitslabel = temp2(21:end);
      
      
      %  Records 12 and up are for data table
      %  Format of each line depends upon:
      %     a) ordinate type (real or complex)
      %     b) ordinate precision (single or double)
      %     c) abscissa spacing (even or uneven)
      
      
      %  Allocate ordinate data vector
      
      orddatamat = zeros(numpts,1);
      
      %  Read data records
      
      switch abscspac
      case 0, % Uneven abscissa spacing
         errordlg('ERROR: uffin_data not equipped to handle uneven abscissa spacing')
         return
      case 1, % Even abscissa spacing (no abscissa values stored in Records 12+)
         switch ordtype,
         case {5,6},  % Complex, single or double precision ordinate values
            eor = 0; % End of record flag
            ocnt = 0; % position of data entry in ordinate
            j = sqrt(-1);
            while ~eor,
               temp = fgetl(fid);
               switch sscanf(temp,'%e',1),
               case -1, eor = 1;   
               otherwise,
                  temp2 = sscanf(temp,'%e',6);
                  for i = 1:length(temp2)/2,
                     orddatamat(ocnt+i,1) = temp2((i-1)*2+1) + j * temp2(i*2);
                  end
                  ocnt = ocnt + i;
               end
            end
         case {2,4}  % Real, single or double precision ordinate values
            eor = 0; % End of record flag
            ocnt = 0; % position of data entry in ordinate
            while ~eor,
               temp = fgetl(fid);
               switch sscanf(temp,'%e',1),
               case -1, eor = 1;   
               otherwise,
                  temp2 = sscanf(temp,'%e',6);
                  orddatamat(ocnt+1:ocnt+length(temp2),1) = temp2;
                  ocnt = ocnt + length(temp2);
               end
            end
         end
      end
      
      % Assign variables to DIAMOND global variables
      
      if funtype == 2, % Signal is APS
         if ordnumforceexp == 2, % Ref. APS  - ref DOF is stored in respnode and respdir
            if isfield(DATA{1},'refDOF'),
               iref = find(DATA{1}.refDOF(:,1) == respnode & DATA{1}.refDOF(:,2) == respdir);
            else
               DATA{1}.refDOF = [];
               iref = [];
            end
            if isempty(iref),
               DATA{1}.refDOF = [DATA{1}.refDOF; [respnode respdir] ];
               iref = size(DATA{1}.refDOF,1);
            end
            iresp = 0;
         else
            if isfield(DATA{1},'respDOF'),
               iresp = find(DATA{1}.respDOF(:,1) == respnode & DATA{1}.respDOF(:,2) == respdir);
            else
               DATA{1}.respDOF = [];
               iresp = [];
            end
            if isempty(iresp),
               DATA{1}.respDOF = [DATA{1}.respDOF; [respnode respdir] ];
               iresp = size(DATA{1}.respDOF,1);
            end
            iref = 1;
         end
      elseif funtype == 1
         if ordnumdatatype == 2, % ref DOF is stored in respnode and respdir
            if isfield(DATA{1},'refDOF'),
               iref = find(DATA{1}.refDOF(:,1) == respnode & DATA{1}.refDOF(:,2) == respdir);
            else
               DATA{1}.refDOF = [];
               iref = [];
            end
            if isempty(iref),
               DATA{1}.refDOF = [DATA{1}.refDOF; [respnode respdir] ];
               iref = size(DATA{1}.refDOF,1);
            end
            iresp = 0;
         else
            if isfield(DATA{1},'respDOF'),
               iresp = find(DATA{1}.respDOF(:,1) == respnode & DATA{1}.respDOF(:,2) == respdir);
            else
               DATA{1}.respDOF = [];
               iresp = [];
            end
            if isempty(iresp),
               DATA{1}.respDOF = [DATA{1}.respDOF; [respnode respdir] ];
               iresp = size(DATA{1}.respDOF,1);
            end
            iref = 1;
         end
      else
         if isfield(DATA{1},'respDOF'),
            iresp = find(DATA{1}.respDOF(:,1) == respnode & DATA{1}.respDOF(:,2) == respdir);
         else
            DATA{1}.respDOF = [];
            iresp = [];
         end
         
         if isempty(iresp),
            DATA{1}.respDOF = cat(1,DATA{1}.respDOF,[respnode respdir]);
            iresp = size(DATA{1}.respDOF,1);
         end
         
         if isfield(DATA{1},'refDOF'),
            iref = find(DATA{1}.refDOF(:,1) == refnode & DATA{1}.refDOF(:,2) == refdir);
         else
            DATA{1}.refDOF = [];
            iref = [];
         end
         
         if isempty(iref),
            DATA{1}.refDOF = [DATA{1}.refDOF; [refnode refdir] ];
            iref = size(DATA{1}.refDOF,1);
         end
         
         if refnode == 0 & refdir == 0,
            iref = 1;
         end
         
      end
         
      if iresp == 1 & iref == 1 & funtype ~= 1,
         DATA{1}.sp = (numpts-1)*abscincr;
         DATA{1}.cf = abscmin + DATA{1}.sp/2;
         DATA{1}.nlines = numpts;
         DATA{1}.t0 = 0;
         DATA{1}.t1 = (numpts-1)/DATA{1}.sp;
         DATA{1}.pathname = pathname;
         DATA{1}.filename = filename;
      end
      
      switch funtype
      case 1 % Time response
         switch ordnumdatatype
         case 9,
            DATA{1}.thist.ref(:,iref,1) = orddatamat;            
         otherwise
            DATA{1}.thist.resp(:,iresp,1) = orddatamat;
         end
      case 2 % Auto-Spectrum
         switch ordnumforceexp
         case 0, % Response APS
            DATA{1}.Gyy(:,iresp,iref,1) = orddatamat;
         case 2, % Reference APS
            DATA{1}.Gxx(:,iref,1) = orddatamat;
         end
      case 3 % Cross-Spectrum
         DATA{1}.Gxy(:,iresp,iref,1) = orddatamat;
      case 4 % Frequency Response Function
         DATA{1}.G(:,iresp,iref,1) = orddatamat;
      case 6 % Coherence
         DATA{1}.Coh(:,iresp,iref,1) = orddatamat;
      end
      
   else
      
      % Find the next -1 -- that will be the end of record
      eor = 0; % End of record flag
      while ~eor,
         temp = sscanf(fgetl(fid),'%e',1);
         if ~isempty(temp),
            if temp == -1, eor = 1; end
         end
      end
      
   end
   
   if feof(fid), eof = 1; end
   
end  % Loop until EOF is reached

return
