1 function [HDR] =
save2bkr(arg1,arg2,arg3);
2 % SAVE2BKR loads EEG data and saves it in BKR format
3 % The following data formats are supported:
4 % CNT, EDF, BKR, MAT, etc. format
6 % HDR =
save2bkr(sourcefile [, destfile [, option]]);
11 % sourcefile sourcefile wildcards are allowed
12 % destfile destination file in BKR format
13 %
if destfile is empty or a directory, sourcefile but with extension .bkr is used.
15 % gain Gain factor
for unscaled EEG data (e.g. old Matlab files)
16 %
'removeDC' removes mean
17 %
'regressEOG k:l,m:n' removes EOG (channels m:n) from EEG (channels k:l)
18 %
'autoscale k:l' uses only channels from k to l
for scaling
19 %
'detrend k:l' channels from k to l are detrended with an FIR-highpass filter.
20 %
'PhysMax=XXX' uses a fixed scaling factor; might be important
for concanating BKR files
21 % +XXX and -XXX correspond to the maximum and minimum physical value, resp.
22 % You can concanate several options by separating with space, komma or semicolon
24 % HDR Header, HDR.FileName must contain target filename
28 %
save2bkr(
'/tmp/*.cnt',[],
'autoscale 5:30');
29 % converts all CNT-files from subdir /tmp/ into BKR files
30 % and saves them in the current directory
31 %
save2bkr(
'/tmp/*.cnt',
'/tmp2/',
'autoscale 5:30, PhysMax=200');
32 % converts all CNT-files from subdir /tmp/ into BKR files
33 % and saves them in the directory /tmp2/
37 % see also: EEGCHKHDR, REGRESS_EOG, SLOAD
40 % $Id:
save2bkr.m 2205 2009-10-27 12:18:15Z schloegl $
41 % Copyright (C) 2002-2003 by Alois Schloegl <a.schloegl@ieee.org>
42 % This is part of the BIOSIG-toolbox http:
44 % This library is free software; you can redistribute it and/or
45 % modify it under the terms of the GNU Library General Public
46 % License as published by the Free Software Foundation; either
47 % Version 2 of the License, or (at your option) any later version.
49 % This library is distributed in the hope that it will be useful,
50 % but WITHOUT ANY WARRANTY; without even the implied warranty of
51 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
52 % Library General Public License
for more details.
54 % You should have received a copy of the GNU Library General Public
55 % License along with
this library;
if not, write to the
56 % Free Software Foundation, Inc., 59 Temple Place - Suite 330,
57 % Boston, MA 02111-1307, USA.
69 if nargin<2, arg2=[]; end;
73 elseif isnumeric(arg3)
76 FLAG_REMOVE_DC = findstr(lower(arg3),
'removedc');
78 tmp = findstr(arg3,
'autoscale');
80 [chansel,tmp] = strtok(arg3(tmp+9:length(arg3)),
' ;+');
81 tmp = str2num(chansel);
83 fprintf(2,
'invalid autoscale argument %s',chansel);
91 tmp = findstr(lower(arg3),
'detrend');
93 [chansel_dt,tmp] = strtok(arg3(tmp+7:length(arg3)),
' ;,+');
94 tmp = str2num(chansel_dt);
96 fprintf(2,
'invalid detrend argument %s',chansel_dt);
104 tmp = findstr(lower(arg3),
'removedrift');
106 [chansel_dt2,tmp] = strtok(arg3(tmp+11:length(arg3)),
' ;+');
107 tmp = str2num(chansel_dt2);
109 fprintf(2,
'invalid RemoveDrift argument %s',chansel_dt2);
112 FLAG_removeDrift = 1;
117 tmp = findstr(lower(arg3),
'regresseog');
119 [chansel_dt3,tmp] = strtok(arg3(tmp+11:length(arg3)),
' ;,+');
120 [chansel_dt4,tmp] = strtok(tmp,
' ;,+');
121 tmp = str2num(chansel_dt3);
122 FLAG_REGRESS_EOG = ~isempty(tmp);
124 fprintf(2,
'invalid REGRESSEOG argument %s',chansel_dt3);
127 FLAG_REGRESS_EOG = 1;
130 tmp = str2num(chansel_dt4);
131 FLAG_REGRESS_EOG = FLAG_REGRESS_EOG * ~isempty(tmp);
133 fprintf(2,
'invalid REGRESSEOG argument %s',chansel_dt4);
139 tmp = findstr(lower(arg3),
'physmax=');
141 [tmp,tmp1] = strtok(arg3(tmp+8:length(arg3)),
' ;,');
142 PHYSMAX = str2num(tmp);
143 if isempty(PHYSMAX ),
144 fprintf(2,
'invalid PhysMax argument %s',tmp);
153 elseif exist(arg1,
'file')
157 elseif exist(arg1,'dir')
158 inpath = fileparts(arg1);
159 infile = dir(arg1); % input file
161 fprintf(2,'ERROR SAVE2BKR: file %s not found.\n',arg1);
165 elseif isstruct(arg1) & isnumeric(arg2),
168 else %if isstruct(arg1) & isnumeric(arg2),
169 fprintf(2,'Error SAVE2BKR: invalid input arguments\n');
174 %HDR.FileName = destfile; % Assign Filename
176 if HDR.NS==size(data,2),
178 elseif HDR.NS==size(data,1),
179 warning('data is transposed\n');
182 fprintf(2,'HDR.NS=%i is not equal number of data columns %i\n',HDR.NS,size(data,2));
186 HDR.NS = size(data,2); % number of channels
188 if ~isfield(HDR,'NRec'),
189 HDR.NRec = 1; % number of trials (1 for continous data)
191 HDR.SPR = size(data,1)/HDR.NRec; % number of samples per trial
192 %HDR.SampleRate = 100; % Sampling rate
193 %HDR.Label = hdr.Label; % Labels,
195 %HDR.PhysMax = max(abs(data(:))); % Physical maximum
196 %HDR.DigMax = max(2^15-1); % Digital maximum
197 % --- !!! Previous scaling gave an error up to 6% and more !!! ---
199 %HDR.Filter.LowPass = 30; % upper cutoff frequency
200 %HDR.Filter.HighPass = .5; % lower cutoff frequency
201 HDR.FLAG.REFERENCE = ' '; % reference '', 'LOC', 'COM', 'LAP', 'WGT'
202 %HDR.FLAG.REFERENCE = HDR.Recording;
203 HDR.FLAG.TRIGGERED = HDR.NRec>1; % Trigger Flag
207 data = data - repmat(mean(data,1),size(data,1),1);
212 tmp = data(:,chansel);
213 HDR.PhysMax = max(abs(tmp(:))); %gives max of the whole matrix
214 HDR.DigMax = 2^15-1; % maximum resulution
217 data(:,k) = data(:,k)*HDR.DigMax/HDR.PhysMax;
219 mm = max(abs(data(:,k)));
220 data(:,k) = data(:,k)*HDR.DigMax/mm;
223 HDR.FLAG.UCAL = 1; % data is de-calibrated, no rescaling within SWRITE
224 %HDR = eegchkhdr(HDR);
227 HDR =
sopen (HDR,'w',0); % OPEN BKR FILE
228 HDR =
swrite(HDR,data); % WRITE BKR FILE
229 %fwrite(HDR.FILE.FID,data','int16'); % WRITE BKR FILE
230 HDR =
sclose(HDR); % CLOSE BKR FILE
233 if isfield(HDR,'Classlabel'),
234 fid = fopen([HDR.FileName(1:length(HDR.FileName)-4) '.par'],'wt');
235 fprintf(fid, '%i\n', HDR.Classlabel);
238 if isfield(HDR,'ArtifactSelection'),
239 fid = fopen([HDR.FileName(1:length(HDR.FileName)-4) '.sel'],'w');
240 fprintf(fid, '%i\r\n', HDR.ArtifactSelection);
246 HDR =
sopen(HDR.FileName,'r');
249 fprintf(2,'Error SAVE2BKR: saving file %s failed\n',HDR.FileName);
254 for k=1:length(infile);
255 filename = fullfile(inpath,infile(k).name);
256 [pf,fn,ext] = fileparts(filename);
259 [y,HDR] =
sload(filename);
261 % load classlabels if the exist
262 tmp = fullfile(HDR.FILE.Path,[HDR.FILE.Name,'.mat']);
265 if isfield(tmp,'classlabel');
266 HDR.Classlabel = tmp.classlabel;
271 fprintf(2,'Error SAVE2BKR: file %s not found\n',filename);
275 if ~isfield(HDR,'NS'),
276 warning(['number of channels undefined in ',filename]);
279 if ~HDR.FLAG.TRIGGERED,
283 if ~isfield(HDR,'NRec'),
286 if ~isfield(HDR,'SPR'),
287 HDR.SPR = size(y,1)/HDR.NRec;
288 elseif length(HDR.SPR)>1, % use just one sampling rate
289 HDR.SPR = HDR.AS.MAXSPR;
290 HDR.SampleRate = HDR.AS.MAXSPR/HDR.Dur;
292 PHYSMAX = max(abs(y(:)));
297 fprintf(1,'\tREGRESS_EOG \n');
302 fprintf(1,'\tREMOVE_DC \n');
303 y = y - repmat(mean(y,1),size(y,1),1);
306 B = -ones(1,HDR.SampleRate)/HDR.SampleRate;
307 B(HDR.SampleRate/2) = B(HDR.SampleRate/2)+1;
310 %HDR.Filter.B=B;%conv(-B, HDR.Filter.B);
313 HDR.Filter.HighPass = .5;
316 tmp = filter(B,1,[y(:,k);zeros(length(B),1)]);
317 y(:,k) = tmp(Delay+1:size(y,1)+Delay);
322 B = .5*(1 - cos(2*pi*(1:4*HDR.SampleRate+1)'/(4*HDR.SampleRate+2)));
324 B(2*HDR.SampleRate) = B(HDR.SampleRate)+1;
326 B = -ones(1,HDR.SampleRate)/HDR.SampleRate;
327 B(HDR.SampleRate/2) = B(HDR.SampleRate/2)+1;
332 %HDR.Filter.B=B;%conv(-B, HDR.Filter.B);
333 Delay = (length(B)-1)/2;
335 HDR.Filter.HighPass = .5;
338 y(:,k) = filtfilt(B,1,y(:,k));
339 %y(:,k) = tmp(Delay+1:size(y,1)+Delay);
348 if isfield(HDR,'EVENT')
349 if ~length(HDR.EVENT.TYP),
351 % TypeList = unique(HDR.EVENT.TYP); but ignores NaN's
352 [sY ,idx] = sort(HDR.EVENT.TYP(:));
353 TypeList = sY([1;find(diff(sY,1)>0)+1]);
355 event = zeros(size(y,1),length(TypeList));
356 for k2 = 1:length(TypeList),
357 tmp = (HDR.EVENT.TYP==TypeList(k2));
358 event(HDR.EVENT.POS(tmp),k2) = HDR.EVENT.TYP(tmp);
360 HDR.NS = HDR.NS + size(event,2);
362 elseif all(HDR.EVENT.TYP < 256), % only NeuroScan Events are converted into separate channels
365 tmp = bitand(HDR.EVENT.TYP,2^k1);
368 event(size(y,1),K) = 0;
369 event(HDR.EVENT.POS(tmp>0),K) = 1;
372 if any(sum(event,2)>1),
373 fprintf(2,'Warning SAVE2BKR: simulateneous events occur. \n');
375 HDR.NS = HDR.NS + size(event,2);
380 % re-scale data to account for the scaling factor in the header
383 HDR.PhysMax = PHYSMAX;
386 HDR.PhysMax = max(abs(tmp(:))); %gives max of the whole matrix
390 y(:,k) = y(:,k)*HDR.DigMax/HDR.PhysMax; % keep correct scaling factor
392 mm = max(abs(y(:,k)));
393 y(:,k) = y(:,k)*HDR.DigMax/mm; % scale to maximum resolution
396 HDR.FLAG.UCAL = 1; % data is de-calibrated, no rescaling within SWRITE
398 tmp = round(HDR.PhysMax);
399 fprintf(1,'Rounding of PhysMax yields %f%% error.\n',abs((HDR.PhysMax-tmp)/tmp)*100);
402 HDR.FLAG.REFERENCE = ' ';
403 HDR.FLAG.TRIGGERED = (HDR.NRec>1);
405 if isempty(outfile), % default destination directory
406 ix = max(find(filename=='.'));
407 %HDR.FileName = [filename(1:ix-1),'.bkr']; % destination directory is same as source directory
408 HDR.FileName = [HDR.FILE.Name,'.bkr']; % destination directory is current working directory
409 elseif isdir(outfile), % output file
410 HDR.FILE.Path = outfile;
411 HDR.FileName = fullfile(outfile,[HDR.FILE.Name,'.bkr']);
413 [HDR.FILE.Path,HDR.FILE.Name,Ext] = fileparts(outfile);
414 HDR.FileName = fullfile(HDR.FILE.Path,[HDR.FILE.Name,Ext]);
416 %HDR = eegchkhdr(HDR);
418 HDR =
sopen(HDR,'w');
420 fprintf(1,'Error SAVE2BKR: couldnot open file %s.\n',HDR.FileName);
424 HDR =
swrite(HDR,y(:,1:HDR.NS)); % WRITE BKR FILE
425 %count = fwrite(HDR.FILE.FID,y','
short');
429 if isfield(HDR,'Classlabel'),
430 if ~isempty(HDR.Classlabel),
431 fid = fopen([HDR.FileName(1:length(HDR.FileName)-4) '.par'],'w');
432 fprintf(fid, '%i\r\n', HDR.Classlabel);
436 if isfield(HDR,'ArtifactSelection'),
437 fid = fopen([HDR.FileName(1:length(HDR.FileName)-4) '.sel'],'w');
438 fprintf(fid, '%i\r\n', HDR.ArtifactSelection);
444 HDR =
sopen(HDR.FileName,'r');
447 fprintf(2,'Error SAVE2BKR: saving file %s failed\n',HDR.FileName);