% SNAPREAD - Read data in Snap-Master Standard Binary Data File Format
% Reads Snap-Master header and data matrix (nchans,nframes).
% Ref: Users Guide, Snap-Master for Windows (1997) p. 4-19
% Usage:
% >> data = snapread(filename); % read .SMA file data
% >> [data,params,events,head] = snapread(filename,seekframes);
% % save parameters, event list
% Inputs:
% filename = string containing whole filename of .SMA file to read
% seekframes = skip this many initial time points {default 0}
% Output:
% data = data matrix, size(nchans,nframes)
% params = [nchannels, nframes, srate]
% events = vector of event frames (lo->hi transitions on event channel);
% See source to set EVENT_CHANNEL and EVENT_THRESH.
% head = complete char file header
%
% Authors: Scott Makeig & Tzyy-Ping Jung, SCCN/INC/UCSD, La Jolla, January 31, 2000
% Copyright (C) January 31, 2000 from PLOTDATA Scott Makeig & Tzyy-Ping Jung, SCCN/INC/UCSD,
% scott@sccn.ucsd.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.
% Scott Makeig & Tzyy-Ping Jung, CNL / Salk Institute / January 31, 2000
% 7-13-00 fixed fprintf count print bug -sm
% 7-13-00 added arg seekframes -sm & ss
% 7-13-00 added test for file length -sm & ss
% 2-15-02 change close('all') to fclose('all') -ad
% 2-15-02 reformated help & license -ad
function [data,params,events,head] = snapread(file,seekframes)
EVENT_CHANNEL = 1; % This channel assumed to store event pulses only!
EVENT_THRESH = 2.3; % Default event threshold (may need to adjust!!!!)
if nargin < 2
seekframes = 0;
end
data = [];
events = [];
params = [];
head = [];
%
%%%%%%%%%%%%%%%%%%%%%%%%%% Open file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
fid = fopen(file,'r', 'ieee-le');
if fid<1
fprintf('\nsnapread(): Could not open file %s.\n\n',file)
return
else
fprintf('\n Opened file %s for reading...\n',file);
end
%
%%%%%%%%%%%%%%%%%%%%%%%%%% Read header %%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Read header and extract info
numbegin=0;
head = [];
while ~numbegin,
line =fgets(fid);
head = [head line];
if (length(line)>=8 && all(line(1:8)=='"NCHAN%"'))
nchans=str2num(line(findstr(line,'=')+1:end-1));
end
if (length(line)>= 12 && all(line(1:12)=='"NUM.POINTS"'))
nframes=str2num(line(findstr(line,'=')+1:end-1));
end
if (length(line)>= 10 && all(line(1:10)=='"ACT.FREQ"'))
srate=str2num(line(findstr(line,'=')+1:end-1));
end
if (length(line)>= 4 && all(line(1:4)=='"TR"'))
head = head(1:length(head)-length(line));
line =fgets(fid); % get the time and date stamp line
numbegin=1;
end
end
params = [nchans, nframes, srate];
fprintf(' Number of channels: %d\n',nchans);
fprintf(' Number of data points: %d\n',nframes);
fprintf(' Sampling rate: %3.1f Hz\n',srate);
fseek(fid,1,0); % skip final hex-AA char
%
%%%%%%%%%%%%%%%%%%% Test for correct file length %%%%%%%%%%%%%%%%%%%%
%
datstart = ftell(fid); % save current position in file
fseek(fid,0,'eof'); % go to file end
datend = ftell(fid); % report position
discrep = (datend-datstart) - nchans*nframes*4;
if discrep ~= 0
fprintf(' ***> Note: File length does not match header information!\n')
fprintf(' Difference: %g frames\n',discrep/(4*nchans));
end
fseek(fid,datstart,'bof'); % seek back to data start
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Read data %%%%%%%%%%%%%%%%%%%%%%%%%%
%
if seekframes > 0
fprintf(' Omitting first %d frames of data.\n',seekframes)
fprintf('moving %d bytes\n',seekframes*nchans*4);
fsq = fseek(fid,seekframes*nchans*4,'cof')
if fsq<0
fsqerr = ferror(fid);
fprintf('fseek() error: %s\n',fsqerr);
return
end
end
[data count] = fread(fid,[nchans,nframes],'float'); % read data frame
if count<nchans*(nframes-seekframes)
fprintf('\nsnapread(): Could not read %d data frames.\n Only %g read.\n\n',...
nframes,count/nchans);
return
else
fprintf('\n Read %d frames, each one sync channel(%d) and %d data channels.\n',...
nframes,EVENT_CHANNEL,nchans-1);
end
if nargout>2
fprintf(' Finding event transitions (>%g) on channel %d ...\n',...
EVENT_THRESH,EVENT_CHANNEL);
events = zeros(EVENT_CHANNEL,nframes);
for n=2:nframes
if abs(data(EVENT_CHANNEL,n-1)) < EVENT_THRESH ...
&& abs(data(EVENT_CHANNEL,n)) > EVENT_THRESH
events(n) = 1;
end
end
fprintf(' Total of %d events found.\n',sum(events));
data = data(2:nchans,:); % eliminate channel 1
fprintf(' Event channel %d removed from output.\n',EVENT_CHANNEL);
params(1) = nchans-1;
end
fprintf('\n');
fclose('all');