classdef TRData
% TRData class
% Container for time-resolved spectroscopy data
% Petar Lambrev, 2011
%
% A TRData dataset contains a 2D array of data (Z) dependent on two variables
% (X and Y) plus additional identifying information, such as ID, units, etc.
% The class is intended for use with time-resolved spectroscopy data.
%
% X is a 1*m array containing the spectral axis (wavelength) values,
% Y is an n*1 array containing the time axis values,
% Z is an n*m array storing the measured quantity (abs, fluorescence, etc.).
%
% Objects of class TRData contain the data themselves as well as
% a number of methods (functions) for data manipulation and presentation.
properties
XType = 'Wavelength'; % type of X-axis data, default - 'Wavelength'
XUnit = 'cm-1'; % unit for X-axis data, default - 'cm-1'
YType = 'Time'; % type of Y-axis data, default - 'Time'
YUnit = 'ps'; % unit for Y-axis data, default - 'ps'
ZType = '\DeltaA'; % type of Z data (measured quantity - Abs, fluorescence, etc.)
ZUnit = 'mOD'; % unit for Z data, default - 'mOD'
X = []; % X-axis data (usually wavelength), 1 x m vector
Y = []; % Y-axis data (usually time), n x 1 vector
Z = []; % Z data, m x n matrix
ID = ''; % dataset ID
ExpID = ''; % experiment ID
Comment = ''; % comments
DateTime = now; % date and time
end
methods
function SP = TRData(X,Y,Z,ID)
% Create a dataset (TRData object)
%
% Usage:
% dat = TRData
% Creates a blank dataset
%
% dat = TRData(X, Y, Z)
% Creates a dataset dat with supplied X, Y and Z values
%
% dat = TRData(X, Y, Z, ID)
% Creates a dataset dat with X, Y, Z values and ID
%
% see also: load
if (nargin == 2),
if (length(X)~=size(Z,2)),
error('Number of elements in X does not match the data');
end
if (length(Y)~=size(Z,1)),
error('Number of elements in Y does not match the data');
end
SP.X = X;
SP.Y = Y;
SP.Z = Z;
end %if
if (nargin == 4),
if (length(X)~=size(Z,2)),
error('Number of elements in X does not match the data');
end
if (length(Y)~=size(Z,1)),
error('Number of elements in Y does not match the data');
end
SP.X = X;
SP.Y = Y;
SP.Z = Z;
SP.ID = ID;
end %if
end %Constructor
%% Queries %%
% --------- %
function n = Xn(SP)
% number of X channels (X data points) in the dataset(s)
n = zeros(1,length(SP));
for i = 1:length(SP),
n(i) = length(SP(i).X);
end %for
end %size
function n = Yn(SP)
% number of Y channels (Y data points) in the dataset(s)
n = zeros(1,length(SP));
for i = 1:length(SP),
n(i) = length(SP(i).Y);
end %for
end %size
function res = Xind(SP,Xval)
% index of the X value(s) specified by Xval.
% Xind = dat.Xind(Xval)
% If dat is an array, Xind will also be an array containing indices
% for each dataset in dat.
res = zeros(1,length(SP));
for i = 1:length(SP),
res(i) = find(SP.X == Xval, 1);
end %for
end %Xind
function res = Yind(SP,Yval)
% index of the Y value(s) specified by Yval.
% Yind = dat.Yind(Yval)
% If dat is an array, Yind will also be an array containing indices
% for each dataset in dat.
res = zeros(1,length(SP));
for i = 1:length(SP),
res(i) = find(SP.Y == Yval, 1);
end %for
end %Xind
function res = Transients(SP,Xval)
% Transients (kinetic traces)
% Transients = Dat.Transients(Xval)
% Returns the kinetic traces Z = f(X) corresponding to wavelengths
% specified by Xval.
n = length(SP);
if (n > 1)
res = cell(1,length(SP));
else
res = [];
end
for i = 1:n,
Xind = zeros(1,length(Xval));
for j = 1:length(Xval)
Xind(j) = find(SP(i).X >= Xval(j), 1);
if (isempty(Xind)), error('X value not found in data'); end
end
if n>1
tres = SP(i).Z(:,Xind);
res{i} = [tres];
else
res = SP(i).Z(:,Xind);
end
end %for
end %Transient
function res = Spectra(SP,Yval)
% Transient spectra
% Spectra = Dat.Spectra(Yval)
% Returns the transient spectra Z = f(X) corresponding to time points
% specified by Yval.
n = length(SP);
if (n > 1)
res = cell(1,length(SP));
else
res = [];
end
for i = 1:n,
Yind = zeros(1,length(Yval));
for j = 1:length(Yval)
Yind(j) = find(SP(i).Y >= Yval(j), 1);
if (isempty(Yind)), error('Y value not found in data'); end
end
if n>1
tres = SP(i).Z(Yind,:)';
res{i} = [tres];
else
res = SP(i).Z(Yind,:)';
end
end %for
end %Spectra
%% Arithmetic operators
% ---------------------
function res = plus(SP1,SP2)
% addition of datasets
%
% Usage:
% new = dat1 + dat2
%
% new contains all values of parameters of dat1 except that
% the Z values are added
%
% see also: minus, times, rdivide
if (~isa(SP1,'Spectrum')),
error('First operand must be a Spectrum object');
end %if
res = SP1;
singlemode = 0;
if (length(SP1)~=length(SP2)),
if(length(SP2)==1),
singlemode = 1;
else
error ('Objects must have the same number of elements');
end %if
end %if
if(isa(SP2,'TRData')),
for i = 1:length(SP1)
if (singlemode), j = 1; else j = i; end
if (SP1(i).dim~=SP2(j).dim), error ('Objects must have the same size'); end
if (SP1(i).X~=SP2(j).X), error ('The X-axes do not match'); end
if (SP1(i).Y~=SP2(j).Y), error ('The Y-axes do not match'); end
res(i).Z = SP1(i).Z + SP2(j).Z;
res(i).Comment = sprintf('%s + %s',SP1(i).Comment,SP2(j).ID);
end %for
elseif(isreal(SP2)),
for i = 1:length(SP1)
if (singlemode), j = 1; else j = i; end
res(i).Z = SP1(i).Z + SP2(j);
res(i).Comment = sprintf('%s + %d',SP1(i).Comment,SP2(j));
end %for
else
error('Unrecognized operand data type');
end %if
end %plus
function res = minus(SP1,SP2)
% subtraction of datasets
%
% Usage:
% new = dat1 - dat2
%
% new contains all values of parameters of dat1 except that
% the Z values are subtracted
%
% see also: plus, times, rdivide
if (~isa(SP1,'TRData')),
error('First operand must be a TRData object');
end %if
res = SP1;
singlemode = 0;
if (length(SP1)~=length(SP2)),
if(length(SP2)==1),
singlemode = 1;
else
error ('Objects must have the same number of elements');
end %if
end %if
if(isa(SP2,'TRData')),
for i = 1:length(SP1)
if (singlemode), j = 1; else j = i; end
if (SP1(i).dim~=SP2(j).dim), error ('Objects must have the same size'); end
if (SP1(i).X~=SP2(j).X), error ('The X-axes do not match'); end
if (SP1(i).Y~=SP2(j).Y), error ('The Y-axes do not match'); end
res(i).Z = SP1(i).Z - SP2(j).Z;
res(i).Comment = sprintf('%s - %s',SP1(i).Comment,SP2(j).ID);
end %for
elseif(isreal(SP2)),
for i = 1:length(SP1)
if (singlemode), j = 1; else j = i; end
res(i).Z = SP1(i).Z - SP2(j);
res(i).Comment = sprintf('%s - %d',SP1(i).Comment,SP2(j));
end %for
else
error('Unrecognized operand data type');
end %if
end %minus
function res = uminus(SP)
% unary minus
% Usage:
% new = -dat1
res = SP;
for i =1:length(SP)
res(i).Z = -SP(i).Z;
end
end %uminus
function res = times(SP1,SP2)
% multiplication of datasets
%
% Usage:
% new = dat1 * dat2
%
% new contains all values of parameters of dat1 except that
% the Z values are multiplied
%
% see also: plus, minus, uminus, rdivide
if (~isa(SP1,'TRData')),
error('First operand must be a TRData object');
end %if
res = SP1;
singlemode = 0;
if (length(SP1)~=length(SP2)),
if(length(SP2)==1),
singlemode = 1;
else
error ('Objects must have the same number of elements');
end %if
end %if
if(isa(SP2,'TRData')),
for i = 1:length(SP1)
if (singlemode), j = 1; else j = i; end
if (SP1(i).dim~=SP2(j).dim), error ('Objects must have the same size'); end
if (SP1(i).X~=SP2(j).X), error ('The X-axes do not match'); end
if (SP1(i).Y~=SP2(j).Y), error ('The Y-axes do not match'); end
res(i).Z = SP1(i).Z .* SP2(j).Z;
res(i).Comment = sprintf('%s * %s',SP1(i).Comment,SP2(j).ID);
end %for
elseif(isreal(SP2)),
for i = 1:length(SP1)
if (singlemode), j = 1; else j = i; end
res(i).Z = SP1(i).Z .* SP2(j);
res(i).Comment = sprintf('%s * %d',SP1(i).Comment,SP2(j));
end %for
else
error('Unrecognized operand data type');
end %if
end %times
function res = mtimes(SP1,SP2)
% see also: times
res = times(SP1,SP2);
end %mtimes
function res = rdivide(SP1,SP2)
% division of datasets
%
% Usage:
% new = dat1 / dat2
%
% new contains all values of parameters of dat1 except that
% the Z values are divided
%
% see also: plus, minus, uminus, times
if (~isa(SP1,'TRData')),
error('First operand must be a TRData object');
end %if
res = SP1;
singlemode = 0;
if (length(SP1)~=length(SP2)),
if(length(SP2)==1),
singlemode = 1;
else
error ('Objects must have the same number of elements');
end %if
end %if
if(isa(SP2,'TRData')),
for i = 1:length(SP1)
if (singlemode), j = 1; else j = i; end
if (SP1(i).dim~=SP2(j).dim), error ('Objects must have the same size'); end
if (SP1(i).X~=SP2(j).X), error ('The X-axes do not match'); end
if (SP1(i).Y~=SP2(j).Y), error ('The Y-axes do not match'); end
res(i).Z = SP1(i).Z ./ SP2(j).Z;
res(i).Comment = sprintf('%s / %s',SP1(i).Comment,SP2(j).ID);
end %for
elseif(isreal(SP2)),
for i = 1:length(SP1)
if (singlemode), j = 1; else j = i; end
res(i).Z = SP1(i).Z ./ SP2(j);
res(i).Comment = sprintf('%s / %d',SP1(i).Comment,SP2(j));
end %for
else
error('Unrecognized operand data type');
end %if
end %rdivide
function res = mrdivide(SP1,SP2)
% see also: rdivide
res = rdivide(SP1,SP2);
end %mrdivide
function res = sum(SP)
% sum of datasets
res = SP(1);
if (length(SP)>1),
for i = 2:length(SP)
res.Z = res.Z + SP(i).Z;
end %for
end %if
end %sum
function res = mean(SP)
% average datasets
%
% see also: average
res = average(SP);
end %mean
function res = max(SP)
% maximal Z value
res = max(SP.Z);
end %max
%% Other calculations
% -------------------
function res = smooth(SP,varargin)
% smooth spectra in the datasets
res = SP;
for i = 1:length(SP)
for x = 1:SP.Xn
res(i).Z(:,x) = smooth(SP(i).Z(:,x),varargin{:});
end
end
end %smooth
function res = brushX(SP,Xi)
% discard data in deffective channels
% and replace with interpolated value
%
% Usage:
% NewData = Dat.brushX(Xi)
%
% Erases data in the selected X channel(s) but does not remove
% the channels. Instead, the data are interpolated (linearly)
% from the neighbouring X channels.
% In contrast to dumpX, brushX does not change the X axis.
%
% see also: dumpX, dumpY
res = SP;
for i = 1:length(SP)
% for each channel
for j = 1:length(Xi)
% find 2 nearest neighbours
if (Xi(j) == 1),
j1 = 2; j2 = 3;
elseif (Xi(j) == SP(i).Xn),
j1 = Xi(j)-1; j2 = Xi(j)-2;
else
j1 = Xi(j)-1; j2 = Xi(j)+1;
end %if
% draw line between 2 points
xi = SP(i).X(Xi(j));
x1 = SP(i).X(j1);
x2 = SP(i).X(j2);
y1 = SP(i).Z(:,j1);
y2 = SP(i).Z(:,j2);
lina = (y2 - y1) ./ (x2 - x1);
linb = y1 - lina .* x1;
% find interpolated values
res(i).Z(:,Xi(j)) = lina .* xi + linb;
end %for
end
end %brushX
function res = dumpX(SP,dumpchn)
% delete X (wavelength) channels
%
% Usage:
% NewData = Dat.dumpX(Xi)
%
% Deletes data in the selected X channel(s).
% Useful when specific detector channels are unreliable or unused.
%
% see also: dumpY, brushX
res = SP;
for i = 1:length(SP)
dumpchn = sort(dumpchn,'descend');
res(i).Z(:,dumpchn) = [];
res(i).X(dumpchn) = [];
end
end %dumpX
function res = dumpY(SP,dumpchn)
% delete Y (time) channels
%
% Usage:
% NewData = Dat.dumpY(Yi)
%
% Deletes data in the selected Y channel(s).
% Useful when specific detector channels are unreliable or unused.
%
% see also: dumpX, brushX
res = SP;
for i = 1:length(SP)
dumpchn = sort(dumpchn,'descend');
res(i).Z(dumpchn,:) = [];
res(i).Y(dumpchn) = [];
end
end %dumpY
function res = setXlim(SP,Xlim)
% set X-axis limits
%
% Usage:
% NewSpectrum = Dat.setXlim([Xmin Xmax])
%
% Sets minimum and maximum limits for the X values.
% Any datapoints lying outside the range specified by Xmin and Xmax
% are deleted.
%
% see also: binX
res = SP;
for i = 1:length(SP)
j = 1;
while (j <= res(i).Xn)
if (res(i).X(j) < Xlim(1)) || (res(i).X(j) > Xlim(2)),
res(i).X(j) = [];
res(i).Z(:,j) = [];
else
j = j + 1;
end %if
end %while
end %for
end %setXlim
function res = setYlim(SP,Ylim)
% set Y-axis limits
%
% Usage:
% NewDat = Dat.setYlim([Ymin Ymax])
%
% Sets minimum and maximum limits for the Y values.
% Any datapoints lying outside the range specified by Ymin and Ymax
% are deleted.
%
% see also: binY
res = SP;
for i = 1:length(SP)
j = 1;
while (j <= res(i).Yn)
if (res(i).Y(j) < Ylim(1)) || (res(i).Y(j) > Ylim(2)),
res(i).Y(j) = [];
res(i).Z(j,:) = [];
else
j = j + 1;
end %if
end %while
end %for
end %setYlim
function res = binX(SP,step)
% bin data across X channels
%
% Usage:
% NewData = Dat.binX(step)
%
% Bins (aggregates) datapoints using the specified X channel step.
% For example if Dat has X datapoints at every 0.1 nm,
% Dat.binX(10) will return a dataset where spectra have 1 nm resolution
% and each new datapoint is an average of 10 original datapoints.
% The binX function is useful to reduce the file size and noise %
% in the data but is also decreases spectral resolution.
%
% see also: setXlim, binY
res = SP;
for i = 1:length(SP)
bins = fix(SP(i).Xn/step);
res(i).X = zeros(1,bins);
res(i).Z = zeros(SP(i).Yn,bins);
for j = 1:bins
ia = (j-1)*step + 1;
ib = j*step - 1;
res(i).X(j) = mean(SP(i).X(ia:ib));
res(i).Z(:,j) = mean(SP(i).Z(:,ia:ib),2);
end %for
end %for
end %binZ
function res = binY(SP,step)
% bin data across Y channels
%
% Usage:
% NewData = Dat.binY(step)
%
% Bins (aggregates) datapoints using the specified Y channel step.
% The binY function is useful to reduce the file size and noise
% in the data but it also decreases time resolution.
%
% see also: binX
res = SP;
for i = 1:length(SP)
bins = fix(SP(i).Yn/step);
res(i).Y = zeros(bins,1);
res(i).Z = zeros(bins,SP(i).Xn);
for j = 1:bins
ia = (j-1)*step + 1;
ib = j*step - 1;
res(i).Y(j) = mean(SP(i).Y(ia:ib));
res(i).Z(j,:) = mean(SP(i).Z(ia:ib,:),1);
end %for
end %for
end %binY
function res = average(SP)
% create average dataset
%
% Usage:
% NewData = Dat.average
% NewData = average(Dat1, Dat2, )
%
% Creates a new dataset which is an average of all datasets
% in the object Dat (or the objects Dat1, Dat2, ).
% Datasets can only be averaged if their X and Y axes are identical.
if (length(SP) < 2)
fprintf('Warning! Number of datasets is less than two. Nothing to average.\n');
res = SP; return;
else
fprintf('Averaging %g datasets... ',length(SP));
Zsum = SP(1).Z;
for i = 2:length(SP)
if (~isequal(SP(1).X,SP(i).X)), error('X values do not match'); end
if (~isequal(SP(1).Y,SP(i).Y)), error('Y values do not match'); end
if (~isequal(size(SP(1)),size(SP(2)))), error('data dimensions do not match'); end
Zsum = Zsum + SP(i).Z;
end %for
res = SP(1);
res.Z = Zsum ./ length(SP);
end %if
fprintf('Done.\n');
end %average
function res = baselineY(SP,Xchn)
% subtract transient baseline
%
% Usage:
% NewData = Dat.baselineY(Xi)
%
% Subtracts baseline from the time traces.
% The baseline time trace is an average the time traces at wavelength channels Xi.
% The transient baseline can be taken at wavelengths where the signal %
% (absorbance/fluorescence/etc) from the sample is negligible.
%
% see also: baselineX
res = SP;
for i = 1:length(SP)
baseoff = mean(SP(i).Z(:,Xchn),2);
for j = 1:SP(i).Xn
res(i).Z(:,j) = res(i).Z(:,j) - baseoff;
end
end %for
end %baselineY
function res = baselineX(SP,Ychn)
% subtract spectral baseline
%
% Usage:
% NewData = Dat.baselineX(Yi)
%
% Subtracts baseline from the spectra.
% The baseline spectrum is the average of the spectra at Y channels Yi.
% Usually the data at times pre zero contain the spectral baseline.
%
% see also: baselineY
res = SP;
for i = 1:length(SP)
baseoff = mean(SP(i).Z(Ychn,:),1);
for j = 1:SP(i).Yn
res(i).Z(j,:) = res(i).Z(j,:) - baseoff;
end
end %for
end %baselineY
%% Save
function saveTIMP(SP,filename)
% Save spectra as ASCII file formatted for TIMP (wavelength-explicit).
%
% Usage:
% dat.save(filename)
%
% If dat contains more than one dataset, they are saved as separate files.
% filename can be a single string or a cell array of strings:
% {file1, file2, } for each dataset.
% If a single file name is given, numbers will be appended to the filename
% to identify each dataset.
%
% To save the data as a MATLAB file (.mat) instead,
% use the MATLAB built-in save command:
% save filename dat
for i=1:length(SP)
s = size(SP(i).Z,2);
if(nargin>=2)
if(iscell(filename))
fout = filename{i};
else
if (i > 1)
fout = strcat(filename,sprintf('%g.ascii',i));
else
fout = filename;
end
end
else
fout = strcat(SP(i).ID,'.ascii');
end
fprintf('Saving %s... ',fout);
fid = fopen(fout,'wt');
fprintf(fid,'%s\n',SP(i).ID);
fprintf(fid,'%s\n',SP(i).Comment);
fprintf(fid,'%s\n','Wavelength explicit');
fprintf(fid,'Intervalnr %d\n\t',s);
fprintf(fid,'%0g\t',SP(i).X(1:s-1));
fprintf(fid,'%0g\n',SP(i).X(s));
for j = 1:length(SP(i).Y)
fprintf(fid,'%0g\t',SP(i).Y(j));
fprintf(fid,'%0g\t',SP(i).Z(j,1:s-1));
fprintf(fid,'%0g\n',SP(i).Z(j,s));
end
fclose(fid);
fprintf('Done.\n');
end
end
%% Plotting
function plotSurface(SP,viewmode)
% plot data as a 2D colour map
if(length(SP)>1)
fprintf('Warning! Only first dataset will be plotted.');
SP = SP(1);
end
Cmax = max(abs(SP.Z(:)))/1.5;
cl = length(colormap)/2;
C = fix((SP.Z ./ Cmax + 1) .* cl);
surf(SP.X,SP.Y,SP.Z,C,'CDataMapping','direct');
if (SP.X(end)<SP.X(1)), set(gca,'Xdir','rev'); end
%set(gca,'YScale','log');
shading interp;
if (exist('viewmode')), view(viewmode), else view(2), end;
xlabel(sprintf('%s (%s)',SP.XType, SP.XUnit));
ylabel(sprintf('%s (%s)',SP.YType, SP.YUnit));
end %surface
function plotSpectra(SP,SelY,varargin)
% plot spectra at selected time points
%
% Usage:
% dat.plotSpectra(Y,Options)
%
% Time-resolved spectra are plotted for each time point in the array Y.
% If exact match is not found, the next larger time point is plotted.
%
% Optional parameters:
% 'Smooth' or 'Smooth','yes' - spectra are plotted as smooth lines
% 'Smooth', 'no' - spectra are plotted as straight lines (default)
%
% see also: plotTransients
if (length(SP)>1), SP = SP(1); end;
% Optional parameters
ShowExpID = false;
NoTeX = false;
SmoothL = false;
if nargin > 2,
for i = 1:nargin-2
switch(lower(varargin{i}))
case 'smooth'
% if 'smooth' is the last argument then
% assume smooth = yes
if (nargin>(i+2)),
smootharg = lower(varargin{i+1});
else
smootharg = 'yes';
end
switch smootharg
case 'no'
SmoothL = false;
case 'false'
SmoothL = false;
otherwise
SmoothL = true;
end
end %switch
end %for
end %if
if (~isempty(SelY))
for i = 1:length(SelY)
fy = find(SP.Y >= SelY(i),1);
if(isempty(fy)), error 'The selected Y values are not found in the dataset.'; end
if (SmoothL == true),
[plX,plY] = smoothLine(SP.X,SP.Z(fy,:));
else
plX = SP.X; plY = SP.Z(fy,:);
end
plot(plX,plY);
hold all
l{i} = sprintf('%g %s', SelY(i),SP.YUnit);
end
if (SP.X(end)<SP.X(1)), set(gca,'Xdir','rev'); end
legend(l,'location','NorthEast','FontSize',11);
legend boxoff
xlabel(sprintf('%s (%s)',SP.XType, SP.XUnit));
ylabel(sprintf('%s (%s)',SP.ZType, SP.ZUnit));
end
end %spectra
function plotTransients(SP,SelX)
% plot time traces at selected wavelengths
%
% Usage:
% dat.plotSpectra(X)
%
% Time traces are plotted for each wavelength in the array X.
% If exact wavelength match is not found, the next larger
% wavelength is plotted.
%
% see also: plotSpectra
if (length(SP)>1), SP = SP(1); end;
for i = 1:length(SelX)
plot(SP.Y,SP.Z(:,find(SP.X >= SelX(i),1),:));
hold all
l{i} = sprintf('%g %s', SelX(i),SP.XUnit);
end
legend(l,'location','NorthEast','FontSize',11);
xlabel(sprintf('%s (%s)',SP.YType, SP.YUnit));
ylabel(sprintf('%s (%s)',SP.ZType, SP.ZUnit));
end %Transients
end %methods
methods (Static)
function spect = load(filepattern,options, firstrecord, lastrecord)
% load data from ASCII text file(s)
%
% Usage:
% dat = TRData.load(filepattern, options)
%
% The files must contain only numerical data arranged in columns.
% The first column of the data must contain time points
% The following columns contain the measured data,
% where each column represents a wavelength channel.
%
% If time points occur several times (e.q. in repeated scan
% measurements), the data are averaged.
% filepattern can specify one or more filenames (e.g. *.DAT).
% If several files match the criteria, then dat is a cell
% array of datasets dat(1), dat(2), - for each file.
% options a structure specifying optional parameters (as fields):
% XType, XUnit, ExpID, Comment.
% The X axis also can be specified here,
% otherwise it will contain consecutive number
% (X values are not read from the file).
% IDs are not specified here but will carry the file names.
if (iscell(filepattern)),
files = filepattern;
else
files = getdir(filepattern);
end %if
if (~iscell(files)) , error('No files selected.'); end
if (length(files)<1), error('No files selected.'); end
fn = length(files);
%data = cell(1,fn);
for i = 1:fn
fprintf('Loading file %s... ',files{i});
store = load(files{i});
% check number of time points
timepoints = unique(store(:,1));
tn = length(timepoints);
cn = size(store,2); % number of columns
rn1 = size(store,1)/tn; % number of records (scans)
rn = fix(rn1);
if (rn1 > rn)
fprintf('Warning: Partial record will be ignored.\n');
end
if (rn < 1),
error('No valid records found in file.');
end
if (rn > 1),
% average if many records
jstart = 1;
jend = rn;
if (nargin>=3),
jstart = firstrecord;
end
if (nargin>=4),
jend = lastrecord;
end;
idata = zeros(tn,cn);
idata(:,1) = store(1:tn,1);
for j = jstart:jend
idata(:,2:cn) = idata(:,2:cn) + store(j*tn-tn+1:j*tn,2:cn);
end;
idata(:,2:cn) = idata(:,2:cn)/rn;
data = idata;
else
% only one record
data = store;
end;
fprintf('Done, %g record(s) read, %g time points.\n',rn, tn);
cols = size(data,2);
Y = data(:,1);
Z = data(:,2:cols);
X = 1:cols-1;
spect(i) = TRData(X,Y,Z,files{i});
if (nargin < 2),
options = struct;
end
if (isfield(options,'XType')),
spect(i).XType = options.XType;
end
if (isfield(options,'YType')),
spect(i).YType = options.YType;
end
if (isfield(options,'ZType')),
spect(i).ZType = options.ZType;
end
if (isfield(options,'XUnit')),
spect(i).XUnit = options.XUnit;
end
if (isfield(options,'YUnit')),
spect(i).YUnit = options.YUnit;
end
if (isfield(options,'ZUnit')),
spect(i).ZUnit = options.ZUnit;
end
if (isfield(options,'Comment')),
spect(i).Comment = options.Comment;
end
if (isfield(options,'ExpID')),
spect(i).ExpID = options.ExpID;
end
if (isfield(options,'X')),
if (~isequal(size(options.X),size(spect(i).X))),
error('Number of X values does not match the dataset.');
end
spect(i).X = options.X;
else
spect(i).XUnit = '';
spect(i).XType = 'Channel No.';
end
end
end %loadData
end %Static
end