Code covered by the BSD License  

Highlights from
UFF File Reading and Writing

image thumbnail

UFF File Reading and Writing

by

 

26 Nov 2004 (Updated )

Reading and writing of ascii files in Universal File Format (UFF).

writeuff(fileName, UffDataSets, action)
function Info = writeuff(fileName, UffDataSets, action)
%WRITEUFF Writes UFF (Universal File Format) files of eight types:
%   151, 15, 55, 1858, 58, 82, 164, 2420, and also the hybrid one, 58b
%   Info = writeuff(fileName, UffDataSets, action)
%
%   Works in Matlab/Octave.
%
%
%   - fileName:     name of the uff file to write data to (add or replace - see action parameter)
%   - UffDataSets:  an array of structures; each structure holds one data set
%                   (the data set between -1 and -1; Each structure,
%                   UffDataSets{i}, has the field
%                       .dsType
%                       .binary
%                   and some additional, data-set dependent fields (some of
%                   them are optional) and are as follows:
%                   #1858 - optional for additional information not contained in
%                           UFF58.  Must be placed just before UFF58.
%                       (Optional fields):
%                       .windowType             .AmpUnits
%                       .NorMethod              .ordNumDataTypeQual
%                       .ordDenomDataTypeQual   .zDataTypeQual
%                       .samplingType           .zRPM
%                       .zTime                  .zOrder
%                       .NumSamples             .expWindowDamping
%                   #58 - for measurement data - function at dof (58). 
%                       .x (time or frequency)  .measData               .d1 (descrip. 1)
%                       .d2 (descrip. 2)        .date                   .functionType (see notes)
%                       .rspNode                .rspDir                 .refNode
%                       .refDir
%                       (Optional fields):
%                       .precision {'single' or 'double'}, defaults to double
%                       .ID_4                   .ID_5                   .loadCaseId
%                       .rspEntName             .refEntName
%                       .abscDataChar           .abscUnitsLabel
%                       .abscLengthUnitsExponent.abscForceUnitsExponent
%                       .abscTempUnitsExponent  .abscAxisLabel
%                       .ordinateLengthUnitsExponent
%                       .ordDataChar            .ordDenomDataChar       
%                       .ordinateNumUnitsLabel  .ordinateDenomUnitsLabel
%                       .zUnitsLabel            .zAxisValue
%                       .ordinateForceUnitsExponent .ordinateTempUnitsExponent
%                       .ordinateAxisLabel
%
%                   #15 - coordinate data (15)  (Grid pts):
%                       .nodeN                  .x                      .y
%                       .z
%                       (Optional fields):
%                       .defCS                  .dispCS                 .color
%
%                   #82 - display Sequence data (82):
%                       .traceNum               .lines
%                       (Optional fields):
%                       .color                  .ID
%
%                   #55 - data at nodes (55):
%                       Common fields:
%                       .analysisType           .dataCharacter = 1      .r1
%                       .r2                     .r3                     .responseType
%                       (Optional fields):
%                       .r4                     .r5                     .r6
%                       Normal modes specific fields (analysisType = 2)
%                       .modeNum                .modeFreq               .modeMass
%                       .mode_v_damping_ratio   .mode_h_damping_ratio
%                       ...or, for complex modes specific fields (analysisType = 3 or 7)
%                       .modeNum                .eigVal                 .modalA
%                       .modalB
%                       ...or, for frequency response specific fields (analysisType = 5)
%                       .freqNum                .freq
%
%                   #151 - header data (151):
%                       .modelName              .description            .dbApp
%                       .dateCreated            .timeCreated            .dbVersion
%                       .dbLastSaveDate         .dbLastSaveTime         .uffApp
%
%                   #164 - units (164):
%                       .unitsCode              .tempMode
%                       Unit factors for converting universal file units to SI. To convert from
%                       universal file units to SI divide by the appropriate factor listed below:
%                       .facLength              .facForce               .facTemp
%                       .facTempOffset
%                       (Optional fields):
%                       .unitsDescription
%
%                   #1860 - transducer calibration data
%                       .serNum
%                       .sensitivity (mV/EU)  (EU set by file type 164)
%                       .dataType (from UFF 58 record 8)
%                       .operatingMode  (1 - voltage, 2 - ICP, 3 - ?)
%                       (Optional fields):
%                       .manufacturer           .model
%                       .calibrationBy          .calibrationDate
%                       .calibrationDueDate     .transducerDescrip
%                       .typeQualifier          .lengthUnitsExp
%                       .forceUnitsExp          .temperatureUnitsExp
%                       .unitsLabel
%
%                   #2420 - coordinate systems (2420):
%                       .partUID                .partName
%                       .csLabels (array)       .csTypes (0=cart. 1=sph. 2=cyl.)
%                       .csColors (array)
%                       .csTrMatrices (cell array of 4x3 transformation matrices for each cs)
%                       (optional)
%                       .csNames (cell array)
%
%   - action:       (optional) 'add' (default) or 'replace'
%
%   - Info:         (optional) structure with the following fields:
%                   .errcode    -   an array of error codes for each data
%                                   ment to be written; 0 = no error otherwise an error occured in data
%                                   set being written - see errmsg
%                   .errmsg     -   error messages (cell array of strings) for each
%                                   data set - empty if no error occured at specific data set
%                   .nErrors    -   number of errors found (unsupported
%                                   datasets, error writing data set,...)
%                   .errorMsgs  -   error messages (empty if no error is found)
%
%   NOTES: r1..r6 are response vectors with node numbers in ROWS and
%   direction in COLUMN (r1=x, r2=y,...,r6=rz).
%
%   functionType can be one of the following:
%               0 - General or Unknown
%               1 - Time Response
%               2 - Auto Spectrum
%               3 - Cross Spectrum
%               4 - Frequency Response Function
%               5 - Transmissibility
%               6 - Coherence
%               7 - Auto Correlation
%               8 - Cross Correlation
%               9 - Power Spectral Density (PSD)
%               10 - Energy Spectral Density (ESD)
%               11 - Probability Density Function
%               12 - Spectrum
%               13 - Cumulative Frequency Distribution
%               14 - Peaks Valley
%               15 - Stress/Cycles
%               16 - Strain/Cycles
%               17 - Orbit
%               18 - Mode Indicator Function
%               19 - Force Pattern
%               20 - Partial Power
%               21 - Partial Coherence
%               22 - Eigenvalue
%               23 - Eigenvector
%               24 - Shock Response Spectrum
%               25 - Finite Impulse Response Filter
%               26 - Multiple Coherence
%               27 - Order Function
%
%   analysisType can be one of the following:
%               0: Unknown
%               1: Static
%               2: (supported) Normal Mode
%               3: (supported) Complex eigenvalue first order
%               4: Transient
%               5: (supported) Frequency Response
%               6: Buckling
%               7: (supported) Complex eigenvalue second order
%
%   dataCharacter can be one of the following:
%               0: Unknown
%               1: Scalar
%               2: 3 DOF Global Translation Vector
%               3: 6 DOF Global Translation & Rotation Vector
%               4: Symmetric Global Tensor
%
%   unitsCode can be one of the following:
%               1 - SI: Meter (newton)
%               2 - BG: Foot (pound f)
%               3 - MG: Meter (kilogram f)
%               4 - BA: Foot (poundal)
%               5 - MM: mm (milli newton)
%               6 - CM: cm (centi newton)
%               7 - IN: Inch (pound f)
%               8 - GM: mm (kilogram f)
%
%   functionType as well as other parameters are described in
%   Test_Universal_File_Formats.pdf
%
%   See also: READUFF
%
%   SOURCES:    [1] Bryce Gardner's read_uff obtained from the internet
%               [2] http://www.sdrl.uc.edu/uff/SDRChelp/LANG/English/unv_ug/book.htm
%
%
%   First release on 02.02.2004
%   Primoz Cermelj, Slovenia
%   Contact: primoz.cermelj@gmail.com
%   Download location: http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=6395&objectType=file
%
%   Version:  1.0.0
%   Last revision: 27.02.2013
%
%   Bug reports, questions, etc. can be sent to the e-mail given above.
%        Known bug - double precision binary abscissa write is in double
%                    precision but must be in single precision
%              (only affects uneven data and readuff has corresponding problem)
%--------------------------------------------------------------------------

%----------------
% WRITEUFF history
%----------------
% [v.1.0.0] 27.02.2013
% - FIX: data-set 151 fields unified (readuff and writeuff)
% [v.0.9.8b7] 17.07.2012
% - FIX: ordinateDenumUnitsLabel changed to ordinateDenomUnitsLabel
% [v.0.9.8b7-v.0.9.8b10] 16.Apr.2012
% - MOD: increased the precision for dx in UFF58 line 7 for PC
% - NEW: added filetype 1860 transducer calibration
% [v.0.9.8b7-v.0.9.8b9] 04.Apr.2012
% - BUG: bug in filetype 82 fixed
% [v.0.9.8b7-v.0.9.8b8] 03.02.2011
% - NEW added single precision writing in binary and ascii
% - FIX limit length of .unitsDescription in UFF164 to 20 characters
% - FIX number of nodes in tracelines
% - NEW added .dbCreateDate .dbCreateDate to UFF151
% - FIX ordDenomLenExp, ordinateDenomUnitsLabel names corrected
% - NEW ordLenExp & ordDenomLenExp (58)
% [v.0.9.8b4-v.0.9.8b7] 30.08.2010
% - FIX: a bug removed when writing data sets 58 (bug appeared along with
%        the last new feature added
% - NEW: function type 12 Spectrum (58)
% - NEW: support for Dataset 1858 added.
% - NEW: ordLenExp & ordDenomLenExp (58)
% - FIX: correct number of bytes written for 58b when uneven data
% - FIX: corrected detection whether the abscissa is even or not
% - FIX: minor changes
% [v.0.9.8b2] 31.01.2006
% - NEW: uneven abscissa data-writing is now supported
% - NEW: 2420 data-set added (coordinate systems)
% [v.0.9.5b1] 06.06.2005
% - NEW: hybrid binary-58 format (58b) is now supported
% - NEW: binary field was added to UffDataSets structures
% [v.0.9.4] 24.05.2005
% - NEW: dsType field is added to UffDataSets structures; dsTypes parameter
%        is no longer needed
%
%----------------

% Notes
% Ideas only reads single precision in binary
% Ideas writes out the Ordinate length units exponent as 2 for auto
% spectrum, 1 for spectrum and 1 for FRF 
% Ideas writes out 1 for the Denominator for the length units exponent
% Ideas units for autopower spectrum requires file 1858 

%--------------
% Check input arguments
%--------------
error(nargchk(2,3,nargin));
if nargin < 3 || isempty(action)
    action = 'add';
end
if ~iscell(UffDataSets)
    error('UffDataSets must be given as a cell array of structures');
end

%--------------
% Open the file for writing
%--------------
machineFormat='n';      % native sets to default for the OS
if strcmpi(action,'replace')
    [fid,ermesage] = fopen(fileName,'w',machineFormat);
else
    [fid,ermesage] = fopen(fileName,'a',machineFormat);
end
if fid == -1,
    error(['could not open file: ' fileName]);
end

%--------------
% Go through all the data sets and write each data set according to its type
%--------------
nDataSets = length(UffDataSets);

Info.errcode = zeros(nDataSets,1);
Info.errmsg = cell(nDataSets,1);
Info.nErrors = 0;

for ii=1:nDataSets
    try
        %
        switch UffDataSets{ii}.dsType
            case {15,82,55,1858,58,151,164,1860,2420}
                fprintf(fid,'%6i%74s\n',-1,' ');
                switch UffDataSets{ii}.dsType
                    case 15
                        Info.errmsg{ii} = write15(fid,UffDataSets{ii});
                    case 82
                        Info.errmsg{ii} = write82(fid,UffDataSets{ii});
                    case 55
                        Info.errmsg{ii} = write55(fid,UffDataSets{ii});
                    case 1858
                        Info.errmsg{ii} = write1858(fid,UffDataSets{ii});
                    case 58
                        Info.errmsg{ii} = write58(fid,UffDataSets{ii});
                    case 151
                        Info.errmsg{ii} = write151(fid,UffDataSets{ii});
                    case 164
                        Info.errmsg{ii} = write164(fid,UffDataSets{ii});
                    case 1860
                        Info.errmsg{ii} = write1860(fid,UffDataSets{ii});
                    case 2420
                        Info.errmsg{ii} = write2420(fid,UffDataSets{ii});
                end
                fprintf(fid,'%6i%74s\n',-1,' ');
            otherwise
                Info.errmsg{ii} = ['Unsupported data set: ' num2str(UffDataSets{ii}.dsType)];
        end
        %
    catch
        fclose(fid);
        error(['Error writing uff file: ' fileName ': ' lasterr]);
    end
end
fclose(fid);

for ii=1:nDataSets
    if ~isempty(Info.errmsg{ii})
        Info.errcode(ii) = 1;
    end
end
Info.nErrors = length(find(Info.errcode));
Info.errorMsgs = Info.errmsg(find(Info.errcode));








%==========================================================================
%                       SUBFUNCTIONS SECTION
%==========================================================================

%--------------------------------------------------------------------------
function errMessage = write15(fid,UFF)
% #15 - Write data-set type 15 data
errMessage = [];
if ispc
    F_13 = '%13.4e';
else
    F_13 = '%13.5e';
end
try
    n = length(UFF.nodeN);
    if ~isfield(UFF,'defCS');   UFF.defCS = zeros(n,1);  end;
    if ~isfield(UFF,'dispCS');  UFF.dispCS = zeros(n,1); end;
    if ~isfield(UFF,'color');   UFF.color = zeros(n,1);  end;
    fprintf(fid,'%6i%74s\n',15,' ');
    for ii=1:n
        fprintf(fid,['%10i%10i%10i%10i' F_13 F_13 F_13 '\n'],UFF.nodeN(ii),UFF.defCS(ii),UFF.dispCS(ii),UFF.color(ii), ...
            UFF.x(ii),UFF.y(ii),UFF.z(ii));
    end
catch
    errMessage = ['error writing coordinate data: ' lasterr];
end
%-----------------------------------------------------------------

%--------------------------------------------------------------------------
function errMessage = write82(fid,UFF)
% #82 - Write data-set type 82 data
errMessage = [];
try
    if ~isfield(UFF,'ID');      UFF.ID = 'NONE'; end;
    if ~isfield(UFF,'color');   UFF.color = 0;  end;
    fprintf(fid,'%6i%74s\n',82,' ');
    fprintf(fid,'%10i%10i%10i\n',UFF.traceNum,length(UFF.lines),UFF.color);  % line 1
    fprintf(fid,'%-80s\n',UFF.ID); % line 2
    fprintf(fid,'%10i%10i%10i%10i%10i%10i%10i%10i\n',UFF.lines); % line 3
    if rem(length(UFF.lines),8)~=0,
        fprintf(fid,'\n');
    end
catch
    errMessage = ['error writing display-sequence data: ' lasterr];
end
%-----------------------------------------------------------------


%--------------------------------------------------------------------------
function errMessage = write55(fid,UFF)
% #55 - Write data-set type 55 data
if ispc
    F_13 = '%13.4e';
else
    F_13 = '%13.5e';
end
errMessage = [];
try
    if isfield(UFF,'r4') & isfield(UFF,'r5') & isfield(UFF,'r6')
        num_data_per_pt = 6;
    else
        num_data_per_pt = 3;
    end

    fprintf(fid,'%6i%74s\n',55,' ');
    fprintf(fid,'%-80s\n','NONE'); %line 1
    fprintf(fid,'%-80s\n','NONE'); %line 2
    fprintf(fid,'%-80s\n','NONE'); %line 3
    fprintf(fid,'%-80s\n','NONE'); %line 4
    fprintf(fid,'%-80s\n','NONE'); %line 5
    if imag(UFF.r1)~=0 & imag(UFF.r2)~=0 & imag(UFF.r3)~=0,
        data_type = 2;
    else
        data_type = 3;
    end
    fprintf(fid,'%10i%10i%10i%10i%10i%10i\n',1,UFF.analysisType,UFF.dataCharacter, ...
        UFF.responseType,data_type,num_data_per_pt); %line 6
    if UFF.analysisType == 2,                               % Normal modes
        fprintf(fid,'%10i%10i%10i%10i\n',2,4,0,UFF.modeNum); %line 7
        fprintf(fid,[F_13 F_13 F_13 F_13 '\n'], ...
            UFF.modeFreq,UFF.modeMass,UFF.mode_v_damping,UFF.mode_h_damping); %line 8
    elseif UFF.analysisType == 5,                           % Frequency Response
        fprintf(fid,'%10i%10i%10i%10i\n',2,1,0,UFF.freqNum); %line 7
        fprintf(fid,'%13.4e\n', UFF.freq); %line 8
    elseif UFF.analysisType == 3 | UFF.analysisType == 7,   % Complex modes
        fprintf(fid,'%10i%10i%10i%10i\n',2,6,0,UFF.modeNum); %line 7
        fprintf(fid,[F_13 F_13 F_13 F_13 F_13 F_13 '\n'], ...
            real(UFF.eigVal),imag(UFF.eigVal),real(UFF.modalA),imag(UFF.modalA), ...
            real(UFF.modalB),imag(UFF.modalB)); %line 8
    else
        errMessage = ['Unsupported analysis type: ' num2str(UFF.analysisType)];
        return
    end
    if data_type == 2,  % real data
        if num_data_per_pt == 3,
            for k=1:length(UFF.nodeNum);
                fprintf(fid,'%10i\n',UFF.nodeNum(k));
                fprintf(fid,[F_13 F_13 F_13 '\n'],UFF.r1(k),UFF.r2(k),UFF.r3(k));
            end
        else
            for k=1:length(UFF.nodeNum);
                fprintf(fid,'%10i\n',UFF.nodeNum(k));
                fprintf(fid,[F_13 F_13 F_13 F_13 F_13 F_13 '\n'], ...
                    UFF.r1(k),UFF.r2(k),UFF.r3(k),UFF.r4(k),UFF.r5(k),UFF.r6(k));
            end
        end
    else               % complex data
        for k=1:length(UFF.nodeNum);
            fprintf(fid,'%10i\n',UFF.nodeNum(k));
            fprintf(fid,[F_13 F_13 F_13 F_13 F_13 F_13 '\n'], ...
                real(UFF.r1(k)),imag(UFF.r1(k)), real(UFF.r2(k)),imag(UFF.r2(k)), ...
                real(UFF.r3(k)),imag(UFF.r3(k)));
        end
    end
    
catch
    errMessage = ['error writing modal data: ' lasterr];
end
%-----------------------------------------------------------------


%--------------------------------------------------------------------------
function errMessage = write1858(fid,UFF)
% #1858 - Write data-set type 1858 data
% Ideas writes this out just before the UFF58 file
% Fortran 1PE15.7 puts one significant digit to the left of the decimal place,
% Matlab's default
if ispc
    F_15 = '%15.6e';
else
    F_15 = '%15.7e';
end
errMessage = [];
try
    if ~isfield(UFF,'windowType');  UFF.windowType = 0; end;
    if ~isfield(UFF,'AmpUnits');  UFF.AmpUnits = 0; end;
    if ~isfield(UFF,'NorMethod');  UFF.NorMethod = 0; end;
    if ~isfield(UFF,'ordNumDataTypeQual');  UFF.ordNumDataTypeQual = 0; end;
    if ~isfield(UFF,'ordDenomDataTypeQual');  UFF.ordDenomDataTypeQual = 0; end;
    if ~isfield(UFF,'zDataTypeQual');  UFF.zDataTypeQual = 0; end;
    if ~isfield(UFF,'samplingType');  UFF.samplingType = 0; end;
    if ~isfield(UFF,'zRPM');  UFF.zRPM = 0; end;
    if ~isfield(UFF,'zTime');  UFF.zTime = 0; end;
    if ~isfield(UFF,'zOrder');  UFF.zOrder = 0; end;
    if ~isfield(UFF,'NumSamples');  UFF.NumSamples = 0; end;
    if ~isfield(UFF,'expWindowDamping');  UFF.expWindowDamping = 0; end;
    fprintf(fid,'%6i%74s\n',1858,' ');
    % Line 1
    fprintf(fid,'%12i%12i%12i%12i%12i%12i        \n',0,0,0,0,0,0);
    % Line 2
    fprintf(fid,'%6i%6i%6i%6i%6i%6i%6i%6i%6i%6i%6i%6i        \n',0,UFF.windowType,UFF.AmpUnits,UFF.NorMethod,0,UFF.ordNumDataTypeQual,UFF.ordDenomDataTypeQual,UFF.zDataTypeQual,UFF.samplingType,0,0,0);
    % Line 3
    fprintf(fid,[ F_15 F_15 F_15 F_15 F_15 '     \n'],0,0,0,0,UFF.expWindowDamping);
    % Line 4
    fprintf(fid,[ F_15 F_15 F_15 F_15 F_15 '     \n'],0,0,0,0,0);
    % Line 5
    fprintf(fid,[ F_15 F_15 F_15 F_15 F_15 '     \n'],0,0,0,0,0);
    % Line 6 (IDeas seems not to follow the 80 character convention)
    fprintf(fid,'%-6s%-74s\n','NONE','NONE');
    % Line 7
    fprintf(fid,'%-80s\n','NONE');
catch
    errMessage = ['error writing modal data: ' lasterr];
end
%--------------------------------------------------------------------------



%--------------------------------------------------------------------------
function errMessage = write58(fid,UFF)
% #58 - Write data-set type 58 data
%
%       Ordinate             Abscissa
% Case  Type    Precision   Spacing    Format
% 1     real    single      even        6E13.5
% 2     real    single      uneven      6E13.5
% 3     complex single      even        6E13.5
% 4     complex single      uneven      6E13.5
% 5     real    double      even        4E20.12
% 6     real    double      uneven      2(E13.5,E20.12)
% 7     complex double      even        4E20.12
% 8     complex double      uneven      E13.5,2E20.12

% For binary unevenly spaced double precision data, the documentation is unclear as to
% whether the abscissa should be single or double precision.  There is some
% indication that perhaps it should be single, but double has been
% implemented here

if ispc
    F_13 = '%13.4e';
    F_20 = '%20.11e';
else
    F_13 = '%13.5e';
    F_20 = '%20.12e';
end
errMessage = [];
try
    if isempty(find(UFF.functionType == [1 2 3 4 6 12], 1))
        errMessage = ['Unsupported function type: ' num2str(UFF.functionType)];
        return
    end
    if ~isfield(UFF,'precision'); UFF.precision='double'; end;
    if ~isfield(UFF,'ID_4');  UFF.ID_4 = 'NONE'; end;
    if ~isfield(UFF,'ID_5');  UFF.ID_5 = 'NONE'; end;
    if ~isfield(UFF,'loadCaseId');  UFF.loadCaseId = 0; end;
    if ~isfield(UFF,'abscLengthUnitsExponent');  UFF.abscLengthUnitsExponent = 0; end;
    if ~isfield(UFF,'abscForceUnitsExponent');  UFF.abscForceUnitsExponent = 0; end;
    if ~isfield(UFF,'abscTempUnitsExponent');  UFF.abscTempUnitsExponent = 0; end;
    if ~isfield(UFF,'abscAxisLabel');  UFF.abscAxisLabel = 'NONE'; end;
    if ~isfield(UFF,'abscUnitsLabel');  UFF.abscUnitsLabel= 'NONE'; end;
    if ~isfield(UFF,'ordinateLengthUnitsExponent');  UFF.ordinateLengthUnitsExponent = 0; end;
    if ~isfield(UFF,'ordinateForceUnitsExponent');  UFF.ordinateForceUnitsExponent = 0; end;
    if ~isfield(UFF,'ordinateTempUnitsExponent');  UFF.ordinateTempUnitsExponent = 0; end;
    if ~isfield(UFF,'ordinateAxisLabel');  UFF.ordinateAxisLabel = 'NONE'; end;
    if ~isfield(UFF,'rspEntName');  UFF.rspEntName = 'NONE'; end;
    if ~isfield(UFF,'refEntName');  UFF.refEntName = 'NONE'; end;
    if ~isfield(UFF,'ordinateNumUnitsLabel');  UFF.ordinateNumUnitsLabel= 'NONE'; end;
    if ~isfield(UFF,'ordLenExp');  UFF.ordLenExp = 0; end;
    if ~isfield(UFF,'ordinateDenomUnitsLabel');  UFF.ordinateDenomUnitsLabel= 'NONE'; end;
    if ~isfield(UFF,'ordDenomLenExp');  UFF.ordDenomLenExp = 0; end;
    if ~isfield(UFF,'zUnitsLabel');  UFF.zUnitsLabel= 'NONE'; end;
    if ~isfield(UFF,'zAxisValue');  UFF.zAxisValue= 0; end;
    if UFF.functionType == 1    % time response
        if ~isfield(UFF,'abscDataChar');  UFF.abscDataChar = 17; end;
        if ~isfield(UFF,'ordDataChar');  UFF.ordDataChar = 8; end;
        if ~isfield(UFF,'ordDenomDataChar');  UFF.ordDenomDataChar = 0; end;
    else                        % frequency response
        if ~isfield(UFF,'abscDataChar');  UFF.abscDataChar = 18; end;
        if ~isfield(UFF,'ordDataChar');  UFF.ordDataChar = 12; end;
        if ~isfield(UFF,'ordDenomDataChar');  UFF.ordDenomDataChar = 13; end;
    end
    %
    isXEven = isempty(find((unique(UFF.x(2:end)-UFF.x(1:end-1))) < eps));
    %
    if imag(UFF.measData)==0
        isXcomplex=0;
    else
        isXcomplex=1;
    end
    
    if     ~isXcomplex && strcmpi(UFF.precision,'single') &&  isXEven; caseID=1;
    elseif ~isXcomplex && strcmpi(UFF.precision,'single') && ~isXEven; caseID=2;
    elseif  isXcomplex && strcmpi(UFF.precision,'single') &&  isXEven; caseID=3;
    elseif  isXcomplex && strcmpi(UFF.precision,'single') && ~isXEven; caseID=4;
    elseif ~isXcomplex && strcmpi(UFF.precision,'double') &&  isXEven; caseID=5;
    elseif ~isXcomplex && strcmpi(UFF.precision,'double') && ~isXEven; caseID=6;
    elseif  isXcomplex && strcmpi(UFF.precision,'double') &&  isXEven; caseID=7;
    elseif  isXcomplex && strcmpi(UFF.precision,'double') && ~isXEven; caseID=8;
    else errMessage = 'Cannot determine data writing case'; return
    end
    
    if UFF.binary
        [filename, mode, machineformat] = fopen(fid);
        if strcmpi(machineformat(1:7),'ieee-le')
            byteOrdering = 1;
        else
            byteOrdering = 2;
        end
        % number of bytes
        switch caseID,
            case 1, % real, single precision, even data
                nBytes=(4+0+0)*length(UFF.measData);
            case 2, % real, single precision, uneven data
                nBytes=(4+0+4)*length(UFF.measData);
            case 3, % complex, single precision, even data
                nBytes=(4+4+0)*length(UFF.measData);
            case 4, % complex, single precision, uneven data
                nBytes=(4+4+4)*length(UFF.measData);
            case 5, % real, double precision, even data
                nBytes=(8+0+0)*length(UFF.measData);
            case 6, % real, double precision, uneven data
                nBytes=(8+0+8)*length(UFF.measData);
            case 7, % complex, double precision, even data
                nBytes=(8+8+0)*length(UFF.measData);
            case 8, % complex, double precision, uneven data
                nBytes=(8+8+8)*length(UFF.measData);
        end
        fprintf(fid,'%6i%1s%6i%6i%12i%12i%6i%6i%12i%12i\n',58,'b',byteOrdering,2,11,nBytes,0,0,0,0);
    else
        fprintf(fid,'%6i%74s\n',58,' ');
    end
    if length(UFF.d1)<=80,
        fprintf(fid,'%-80s\n',UFF.d1);   %  line 1
    else
        fprintf(fid,'%-80s\n',UFF.d1(1:80));   %  line 1
    end
    if length(UFF.d2)<=80,
        fprintf(fid,'%-80s\n',UFF.d2);   %  line 2
    else
        fprintf(fid,'%-80s\n',UFF.d2(1:80));   %  line 2
    end
    if length(UFF.date)<=80,
        fprintf(fid,'%-80s\n',UFF.date);   %  line 3
    else
        fprintf(fid,'%-80s\n',UFF.date(1:80));   %  line 3
    end
    if length(UFF.ID_4)<=80,
        fprintf(fid,'%-80s\n',UFF.ID_4);   %  line 4
    else
        fprintf(fid,'%-80s\n',UFF.ID_4(1:80));   %  line 4
    end
    if length(UFF.ID_5)<=80,
        fprintf(fid,'%-80s\n',UFF.ID_5);   %  line 5
    else
        fprintf(fid,'%-80s\n',UFF.ID_5(1:80));   %  line 5
    end
    %
    fprintf(fid,'%5i%10i%5i%10i %-10s%10i%4i %-10s%10i%4i\n',UFF.functionType,0,0,UFF.loadCaseId,UFF.rspEntName,...
        UFF.rspNode,UFF.rspDir,UFF.refEntName,UFF.refNode,UFF.refDir);    % line 6
    numpt = length(UFF.measData);
    % line 7
    dx = UFF.x(2) - UFF.x(1);
    switch caseID,
        case {1, 2},    % real single precision
            ordDataType=2;
        case {5, 6},    % real, double precision
            ordDataType=4;
        case {3, 4},    % complex, single precision
            ordDataType=5;
        case {7, 8},    % complex, double precision
            ordDataType=6;
    end
%     fprintf(fid,['%10i%10i%10i' F_13 F_13 F_13 '           \n'],ordDataType,numpt,isXEven,isXEven*UFF.x(1),isXEven*dx,UFF.zAxisValue);
    fprintf(fid,'%10i%10i%10i%13.5e%13.5e%13.5e           \n',ordDataType,numpt,isXEven,isXEven*UFF.x(1),isXEven*dx,UFF.zAxisValue);
    % line 8
    fprintf(fid,'%10i%5i%5i%5i %-20s %-20s             \n',UFF.abscDataChar,0,0,0,'NONE',UFF.abscUnitsLabel);
    % line 9
    fprintf(fid,'%10i%5i%5i%5i %-20s %-20s             \n',UFF.ordDataChar,UFF.ordLenExp,0,0,'NONE',UFF.ordinateNumUnitsLabel);
    %                                                      ^--acceleration data
    % line 10
    % others: 0=unknown,8=displacement,11=velocity,13=excitation force,15=pressure
    fprintf(fid,'%10i%5i%5i%5i %-20s %-20s             \n',UFF.ordDenomDataChar,UFF.ordDenomLenExp,0,0,'NONE',UFF.ordinateDenomUnitsLabel);
    %                                                      ^--excitation force data
    % line 11
    % others: 0=unknown,8=displacement,11=velocity,12=acceleration,15=pressure
    fprintf(fid,'%10i%5i%5i%5i %-20s %-20s             \n',0,0,0,0,'NONE',UFF.zUnitsLabel);
    %
    % line 12: % data values
    nOrdValues = length(UFF.measData);
    switch caseID,
        case {1, 5}     % real even data
            newdata = UFF.measData;
        case {2, 6}     % real uneven data
            newdata = zeros(2*nOrdValues,1);
            newdata(1:2:end-1) = UFF.x;
            newdata(2:2:end) = UFF.measData;
        case {3, 7}     % complex even data
            newdata = zeros(2*nOrdValues,1);
            newdata(1:2:end-1) = real(UFF.measData);
            newdata(2:2:end)   = imag(UFF.measData);
        case {4, 8}     % complex uneven data
            newdata = zeros(3*nOrdValues,1);
            newdata(1:3:end-2) = UFF.x;
            newdata(2:3:end-1) = real(UFF.measData);
            newdata(3:3:end)   = imag(UFF.measData);
    end
    
    if UFF.binary
        if strcmp(UFF.precision,'single')
            fwrite(fid,newdata, 'single');
        else
            fwrite(fid,newdata, 'double');
        end
    else    % ascii
        switch caseID,
            case 1, % real, single precision, even data
                fprintf(fid,[F_13 F_13 F_13 F_13 F_13 F_13 '\n'],newdata);
                if rem(length(newdata),6)~=0,
                    fprintf(fid,'\n');
                end
            case 2, % real, single precision, uneven data
                fprintf(fid,[F_13 F_13 F_13 F_13 F_13 F_13 '\n'],newdata);
                if rem(length(newdata),6)~=0,
                    fprintf(fid,'\n');
                end
            case 3, % complex, single precision, even data
                fprintf(fid,[F_13 F_13 F_13 F_13 F_13 F_13 '\n'],newdata);
                if rem(length(newdata),6)~=0,
                    fprintf(fid,'\n');
                end
            case 4, % complex, single precision, uneven data
                fprintf(fid,[F_13 F_13 F_13 F_13 F_13 F_13 '\n'],newdata);
                if rem(length(newdata),6)~=0,
                    fprintf(fid,'\n');
                end
            case 5, % real, double precision, even data
                fprintf(fid,[F_20 F_20 F_20 F_20 '\n'],newdata);
                if rem(length(newdata),4)~=0,
                    fprintf(fid,'\n');
                end
            case 6, % real, double precision, uneven data
                fprintf(fid,[F_13 F_20 F_13 F_20 '\n'],newdata);
                if rem(length(newdata),4)~=0,
                    fprintf(fid,'\n');
                end
            case 7, % complex, double precision, even data
                fprintf(fid,[F_20 F_20 F_20 F_20 '\n'],newdata);
                if rem(length(newdata),4)~=0,
                    fprintf(fid,'\n');
                end
            case 8, % complex, double precision, uneven data
                fprintf(fid,[F_13 F_20 F_20 '\n'],newdata);
                if rem(length(newdata),3)~=0,
                    fprintf(fid,'\n');
                end
        end
    end
    
catch
    errMessage = ['error writing measurement data: ' lasterr];
end
%--------------------------------------------------------------------------

%--------------------------------------------------------------------------
function errMessage = write151(fid,UFF)
% #151 - Write data-set type 151 data
errMessage =[];
try
    d = datestr(now,1);
    d(end-3:end-2) = [];
    if ~isfield(UFF,'dateCreated'); UFF.dateCreated=d; end
    if ~isfield(UFF,'timeCreated'); UFF.timeCreated=datestr(now,13); end
    if ~isfield(UFF,'dbVersion'); UFF.dbVersion = 0; end;
    if ischar(UFF.dbVersion); UFF.dbVersion = str2num(UFF.dbVersion); end;
    if ~isfield(UFF,'dbLastSaveDate'); UFF.dbLastSaveDate=d; end;
    if ~isfield(UFF,'dbLastSaveTime'); UFF.dbLastSaveTime=datestr(now,13); end;
    
    fprintf(fid,'%6i%74s\n',151,' ');
    fprintf(fid,'%-80s\n',UFF.modelName); % line 1
    fprintf(fid,'%-80s\n',UFF.description); % line 2
    fprintf(fid,'%-80s\n',UFF.dbApp); % line 3
    fprintf(fid,'%-10s%-10s%10i%10i%10i%30s\n',...
        UFF.dateCreated,UFF.timeCreated,UFF.dbVersion,UFF.dbVersion,0,' '); % line 4
    fprintf(fid,'%-10s%-10s%60s\n',UFF.dbLastSaveDate,UFF.dbLastSaveTime,' '); % line 5
    fprintf(fid,'%-80s\n',UFF.uffApp); % line 6
    fprintf(fid,'%-10s%-10s%60s\n',d,datestr(now,13),' '); % line 7
catch
    errMessage = ['error writing header data: ' lasterr];
end
%--------------------------------------------------------------------------


%--------------------------------------------------------------------------
function errMessage = write164(fid,UFF)
% #164 - Write data-set type 164 data
errMessage = [];
try
    if ~isfield(UFF,'unitsDescription'); UFF.unitsDescription = ' '; end;
    fprintf(fid,'%6i%74s\n',164,' ');
    if ischar(UFF.tempMode); UFF.tempMode = str2num(UFF.tempMode); end;
    if isempty(UFF.tempMode); UFF.tempMode = 1; end;
    if length(UFF.unitsDescription)>20; UFF.unitsDescription=UFF.unitsDescription(1:20); end;
    fprintf(fid,'%10i%-20s%10i\n',UFF.unitsCode,UFF.unitsDescription,UFF.tempMode); % line 1
    %
    str = lower(sprintf('%25.17e%25.17e%25.17e',UFF.facLength,UFF.facForce,UFF.facTemp)); % line 2
    str = strrep(str,'e+','D+');
    str = strrep(str,'e-','D-');
    fprintf(fid,'%s\n',str);
    str = lower(sprintf('%25.17e',UFF.facTempOffset)); % line 3
    str = strrep(str,'e+','D+');
    str = strrep(str,'e-','D-');
    fprintf(fid,'%s\n',str);
catch
    errMessage = ['error writing units data: ' lasterr];
end
%--------------------------------------------------------------------------


function errMessage = write1860(fid,UFF)
% #1860 - Write data-set type 1860 transducer calibration data
errMessage = [];
if ispc
    F_15 = '%15.6e';
else
    F_15 = '%15.7e';
end
try
    if ~ischar(UFF.serNum); UFF.serNum = num2str(UFF.serNum); end;
    if ~isfield(UFF,'manufacturer'); UFF.manufacturer = 'NONE'; end;
    if ~isfield(UFF,'model'); UFF.model = 'NONE'; end;
    if ~isfield(UFF,'calibrationBy'); UFF.calibrationBy = 'NONE'; end;
    if ~isfield(UFF,'calibrationDate'); UFF.calibrationDate = 'NONE'; end;
    if ~isfield(UFF,'calibrationDueDate'); UFF.calibrationDueDate = 'NONE'; end;
    if ~isfield(UFF,'transducerDescrip'); UFF.transducerDescrip = 'NONE'; end;
    if ~isfield(UFF,'typeQualifier'); UFF.typeQualifier = 0; end;
    if ~isfield(UFF,'lengthUnitsExp'); UFF.lengthUnitsExp = 0; end;
    if ~isfield(UFF,'forceUnitsExp'); UFF.forceUnitsExp = 0; end;
    if ~isfield(UFF,'temperatureUnitsExp'); UFF.temperatureUnitsExp = 0; end;
    if ~isfield(UFF,'unitsLabel'); UFF.unitsLabel = 'NONE'; end;
    fprintf(fid,'%6i%74s\n',1860,' ');
    fprintf(fid,'%-20s\n',UFF.serNum); % line 1
    fprintf(fid,'%-20s  %-20s\n',UFF.manufacturer,UFF.model); % line 2
    fprintf(fid,'%-20s  %-20s  %-20s\n',...
        UFF.calibrationBy,UFF.calibrationDate,UFF.calibrationDueDate); % line 3
    fprintf(fid,'%-80s\n',UFF.transducerDescrip); % line 4
    % Note the two spaces before the unitsLabel are missing in the 
    % documentation file but are present in the file written by Ideas
    fprintf(fid,'%12i%12i%12i%6i%6i%6i  %-20s\n',...
        UFF.operatingMode,UFF.dataType,UFF.typeQualifier,...
        UFF.lengthUnitsExp,UFF.forceUnitsExp,UFF.temperatureUnitsExp,...
        UFF.unitsLabel);                                             % line 5
    fprintf(fid,[F_15 '\n'],UFF.sensitivity); % line 6
catch
errMessage = ['error writing trasducer data: ' lasterr];
end


%--------------------------------------------------------------------------
function errMessage = write2420(fid,UFF)
% #2420 - Write data-set type 2420 data
errMessage = [];
if ispc
    F_25 = '%25.15e';
else
    F_25 = '%25.16e';
end
try
    n = length(UFF.csLabels);
    if ~isfield(UFF,'csNames'); UFF.csNames = cell(n,1); UFF.csNames(1:n) = {' '}; end;
    fprintf(fid,'%6i%74s\n',2420,' ');
    fprintf(fid,'%10i%10i\n',UFF.partUID,0);       % line 1
    fprintf(fid,'%-40s\n',UFF.partName);            % line 2
    for ii=1:n
        fprintf(fid,'%10i%10i%10i%10i\n',...
            UFF.csLabels(ii),UFF.csTypes(ii),UFF.csColors(ii),0);     % line 3
        fprintf(fid,'%-40s\n',UFF.csNames{ii});     % line 4
        fprintf(fid,[F_25 F_25 F_25 '\n'],UFF.csTrMatrices{ii}(1,1:3)); % line 5
        fprintf(fid,[F_25 F_25 F_25 '\n'],UFF.csTrMatrices{ii}(2,1:3)); % line 6
        fprintf(fid,[F_25 F_25 F_25 '\n'],UFF.csTrMatrices{ii}(3,1:3)); % line 7
        fprintf(fid,[F_25 F_25 F_25 '\n'],UFF.csTrMatrices{ii}(4,1:3)); % line 8
    end
    
catch
    errMessage = ['error writing coordinate system data: ' lasterr];
end
%--------------------------------------------------------------------------

Contact us