Revision 4dbf0ec391b877f21402aed9e8351fe8f7468d14 authored by D019 Rig on 19 December 2019, 23:25:22 UTC, committed by D019 Rig on 19 December 2019, 23:25:22 UTC
1 parent 4cac1d4
IBWread.m
function D = IBWread(FN);
% IBWread - read Igor wave from IBW file
% D = IBWread('Foo.ibw') reads Igor file Foo.ibw into struct D.
if exist('fullfilename', 'file'), FFN = fullfilename(FN, cd, '.ibw');
else, FFN = FN;
end
% read headers
[D.binHeader, D.waveHeader, FFN] = readIBWheaders(FN);
fid = fopen(FFN,'r');
fid = fopen(FFN,'r');
% For numeric waves, the type field is interpreted bitwise. One of the following bits, as represented by symbols defined in IgorBin.h, will be set:
%
% % #define NT_CMPLX 1 % Complex numbers.
% % #define NT_FP32 2 % 32 bit fp numbers.
% % #define NT_FP64 4 % 64 bit fp numbers.
% % #define NT_I8 8 % 8 bit signed integer. Requires Igor Pro 2.0 or later.
% % #define NT_I16 0x10 % 16 bit integer numbers. Requires Igor Pro 2.0 or later.
% % #define NT_I32 0x20 % 32 bit integer numbers. Requires Igor Pro 2.0 or later.
% % #define NT_UNSIGNED 0x40 % Makes above signed integers unsigned. Requires Igor Pro 3.0 or later.
% NT_FP64 64-bit floating point (double)
% NT_FP32 32-bit floating point (float)
% NT_I32 32 bit integer (long)
% NT_16 16 bit integer (short)
% NT_I8 8 bit integer (char)
datatype = D.waveHeader.type;
CMPLX = rem(datatype,2);
if CMPLX, datatype = datatype-1; end
switch datatype,
case 0, prec = '*char';
case 2, prec = 'single';
case 4, prec = 'double';
case 8, prec = 'int8';
case 16, prec = 'int16';
case 32, prec = 'int32';
case 64+8, prec = 'uint8';
case 64+16, prec = 'uint16';
case 64+32, prec = 'uint32';
otherwise, error('Invalid numerical datatype.');
end
D.bname = D.waveHeader.bname;
% The date/time is store as seconds since midnight, January 1, 1904.
D.creationDate = local_igorTime2vec(D.waveHeader.creationDate);
D.modDate = local_igorTime2vec(D.waveHeader.creationDate);
switch D.binHeader.version,
case 2,
% The version 2 file has the following general layout.
% BinHeader2 structure: 16 bytes
% WaveHeader2 structure excluding wData field; 110 bytes
% Wave data: Variable size
D.Nsam = D.waveHeader.npnts;
D.Ndim = 1;
% X value for point p = hsA*p + hsB
D.dx = D.waveHeader.hsA;
D.x0 = D.waveHeader.hsB;
D.x1 = D.x0+D.Nsam*D.dx;
fseek(fid, 16+110, 'bof');
NN = D.Nsam*(1+double(CMPLX)); % if complex, read twice as many numbers
D.y = fread(fid, NN, prec);
if CMPLX, D.y = D.y(1:2:end) + i*D.y(2:2:end); end; % Re & Im values are interleaved
case 5,
% The version 5 file has the following general layout.
% BinHeader5 structure 64 bytes
% WaveHeader5 structure excluding wData field 320 bytes
% Wave data Variable size
% Optional wave dependency formula Variable size
% Optional wave note data Variable size
D.Nsam = D.waveHeader.npnts;
D.Ndim = sum(D.waveHeader.nDim>0);
% X offset & spacing (documentation is obscure)
D.dx = D.waveHeader.sfA(1:D.Ndim);
D.x0 = D.waveHeader.sfB(1:D.Ndim);
D.x1 = nan; % D.x0+D.Nsam*D.dx;
fseek(fid, 64+320, 'bof');
NN = D.Nsam*(1+double(CMPLX)); % if complex, read twice as many numbers
if isequal(0,datatype), % text data
% Number of bytes of wave data = wfmSize - (sizeof(WaveHeader5) - 4)
NN = D.binHeader.wfmSize-320;
D.y = fread(fid, NN, prec)';
else, % numerical data
D.y = fread(fid, NN, prec);
end
if CMPLX, D.y = D.y(1:2:end) + i*D.y(2:2:end); end; % Re & Im values are interleaved
if ~isempty(D.y) && D.Ndim>1,
D.y = reshape(D.y, D.waveHeader.nDim(1:D.Ndim));
end
end
D.WaveNotes = local_readNotes(fid, D.binHeader);
if isequal(0,datatype), % partition text data into lines using string indices stored @ eof
D = local_partition_text(fid, D);
end
fseek(fid,0,'eof');
D.fileSize = ftell(fid);
fclose(fid);
%===============================
function DV=local_igorTime2vec(it);
% igor time -> date vector a la Matlab
% The date/time is store as seconds since midnight, January 1, 1904.
Nsec_4year = 126230400;
idate_1988 = 21*uint32(Nsec_4year); % # seconds between 1-jan-1904 & 1-jan-1988
it = double(it-idate_1988); % smaller numbers-> use ordinary numbers ("doubles")
M4 = floor(it/Nsec_4year);
YR = double(1988+4*M4);
it = double(it-M4*Nsec_4year);
last_it = it;
while 1, % subtract years as long as they fit
s = etime([YR+1 1 1 0 0 0], [YR 1 1 0 0 0]);
if it<s, break; end % we went too far
YR = YR+1;
it = it-s;
end
MNTH = 1;
while 1, % subtract months as long as they fit
s = etime([YR MNTH+1 1 0 0 0], [YR MNTH 1 0 0 0]);
if it<s, break; end % we went too far
MNTH = MNTH+1;
it = it-s;
end
DAY = 1;
while 1, % subtract days as long as they fit
s = etime([YR MNTH DAY+1 0 0 0], [YR MNTH DAY 0 0 0]);
if it<s, break; end % we went too far
DAY = DAY+1;
it = it-s;
end
HR = floor(it/60^2); it = it-HR*60^2;
MIN = floor(it/60); SEC = it-MIN*60;
DV = [YR, MNTH, DAY, HR, MIN, SEC];
if ~isequal(last_it, etime(DV, [1988+4*M4 1 1 0 0 0])),
error('date error');
end
function Nts = local_readNotes(fid, B);
switch B.version,
case 2,
% BinHeader2 structure 16 bytes
% WaveHeader2 structure excluding wData field 110 bytes
% Wave data Variable size
% 16 bytes of padding 16 bytes
dum = fread(fid,16,'char');
% Optional wave note data
Nts = fread(fid, B.noteSize, '*char').';
case 5,
% BinHeader5 structure 64 bytes
% WaveHeader5 structure excluding wData field 320 bytes
% Wave data Variable size
% Optional wave dependency formula Variable size
dum = fread(fid,B.formulaSize, 'char');
% Optional wave note data Variable size
Nts = fread(fid, B.noteSize, '*char').';
end
function D = local_partition_text(fid, D);
% read sizeindices and chop text accordingly, must be called after reading
% notes
bH = D.binHeader;
% skip other stuff in file
% The version 5 file has the following general layout.
% BinHeader5 structure 64 bytes
% WaveHeader5 structure excluding wData field 320 bytes
% Wave data Variable size
% Optional wave dependency formula Variable size
% Optional wave note data Variable size
% Optional extended data units data Variable size
% Optional extended dimension units data Variable size
% Optional dimension label data Variable size
% String indices used for text waves only Variable size
dum=fseek(fid, -bH.sIndicesSize, 'eof'); % string indices are last in file; it's easier to refer from end-of-file
% bH.sIndicesSize; # bytes of string indices stored for the wave if the wave type is text.
% String indices are used to determine the offset in the file and the number of bytes for each element of the text wave.
sIdx = [0 fread(fid, bH.sIndicesSize/4, 'uint32').'];
for ii=1:numel(sIdx)-1,
STR{ii,1} = D.y(sIdx(ii)+1:sIdx(ii+1));
end
D.y = STR;
% long sIndicesSize; The size of string indicies if this is a text wave.

Computing file changes ...