1function [argout,H1,h2] = hdr2ascii(source,dest) 2% HDR2ASCII converts the header information into ASCII text. 3% 4% HDR2ASCII(HDR [, ...]); 5% converts file header HDR 6% HDR2ASCII(file [, ...]); 7% converts header of file 8% HDR2ASCII(arg,dest_file); 9% converts file header HDR and writes it into dest_file 10% HDR=HDR2ASCII(...); 11% returns header HDR 12% 13% see also: SLOAD, SOPEN 14 15% Copyright (C) 2007,2008,2020 by Alois Schloegl <alois.schloegl@gmail.com> 16% This is part of the BIOSIG-toolbox http://biosig.sf.net/ 17% 18% This program is free software; you can redistribute it and/or 19% modify it under the terms of the GNU General Public License 20% as published by the Free Software Foundation; either version 3 21% of the License, or (at your option) any later version. 22% 23% This program is distributed in the hope that it will be useful, 24% but WITHOUT ANY WARRANTY; without even the implied warranty of 25% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26% GNU General Public License for more details. 27% 28% You should have received a copy of the GNU General Public License 29% along with this program; if not, write to the Free Software 30% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 31 32if nargin<2, 33 if isstruct(source) 34 HDR = source; 35 elseif ischar(source) 36 if any(source=='*') 37 [s,HDR]=sload(source); 38 else 39 HDR = sopen(source); 40 HDR = sclose(HDR); 41 end; 42 else 43 'not implemented yet', 44 end; 45 dest = [tempname,'.dlm']; 46elseif isstruct(source) && ischar(dest); 47 HDR = source; 48elseif ischar(source) && ischar(dest); 49 HDR = sopen(source); 50 HDR = sclose(HDR); 51else 52 'not implemented yet', 53end; 54if isnan(HDR.NS) && exist('mexSLOAD','file'), 55 [s,HDR]=mexSLOAD(HDR.FileName); 56end 57 58if nargin>1, 59 fid = fopen(dest,'wt'); 60 if fid<0, 61 fprintf(2,'ERROR HDR2ASCII: could not open file %s\n',dest); 62 return; 63 end; 64else 65 fid = 1; 66end; 67 68 69%%%%%%%%% FIXED HEADER %%%%%%%%%%%%%% 70fprintf(fid,'[BioSig Header]\n\n'); 71fprintf(fid,'Version=0.10\n'); 72fprintf(fid,'generated=%04i-%02i-%02i %02i:%02i:%04.1f\n',datevec(now)); 73if fid>2; 74 fprintf(fid,'\n;This is a TAB-delimiter file. When you edit this file, make sure not to corrupt the TABs ASCII(9)!\n\n'); 75 fprintf(fid,'ThisFile=%s\n',dest); 76end; 77 78 79fprintf(fid,'\n[Fixed Header]\n'); 80if isfield(HDR,'FileName') 81 fprintf(fid,'Filename\t= %s\n',HDR.FileName); 82end; 83fprintf(fid,'Format \t= %s\n',HDR.TYPE); 84if isfield(HDR,'FILE') && isfield(HDR.FILE,'size'), fprintf(fid,'SizeOfFile\t= %i\n',HDR.FILE.size); end; 85if ~isfield(HDR,'NS') 86 HDR.NS = 0; 87end; 88fprintf(fid,'NumberOfChannels\t= %i\n',HDR.NS); 89if isfield(HDR,'SampleRate') 90 fprintf(fid,'SamplingRate \t= %f (%i%+g) Hz\n',HDR.SampleRate, round(HDR.SampleRate), HDR.SampleRate-round(HDR.SampleRate)); 91end; 92if isfield(HDR,'NRec') && isfield(HDR,'SPR') 93 fprintf(fid,'Number_of_Samples\t= %i\n',HDR.NRec*HDR.SPR); 94end; 95T0 = zeros(1,6); 96if isfield(HDR,'T0') 97 switch length(HDR.T0) 98 case 1, T0 = datevec(HDR.T0); 99 case 6, T0 = HDR.T0; 100 end; 101 fprintf(fid,'RecordingDateTime\t= %04i-%02i-%02i %02i:%02i:%06.3f\n',T0); 102end; 103if isfield(HDR,'Patient') 104 fprintf(fid,'Patient.\n'); 105 if isfield(HDR.Patient,'Name') 106 fprintf(fid,'\tName \t= %s\n',HDR.Patient.Name); 107 end; 108 if isfield(HDR.Patient,'Id') 109 fprintf(fid,'\tId\t\t= %s\n',HDR.Patient.Id); 110 end; 111 if isfield(HDR.Patient,'Sex') 112 if (HDR.Patient.Sex==1) 113 fprintf(fid,'\tGender \t= male\n'); 114 elseif (HDR.Patient.Sex==2) 115 fprintf(fid,'\tGender \t= female\n'); 116 else 117 fprintf(fid,'\tGender \t= unknown\n'); 118 end; 119 end; 120 T1 = zeros(1,6); 121 if isfield(HDR.Patient,'Birthday') 122 switch length(HDR.Patient.Birthday) 123 case 1, T1 = datevec(HDR.Patient.Birthday); 124 case 6, T1 = HDR.Patient.Birthday; 125 end; 126 if ~any(isnan(T0)) 127 fprintf(fid,'\tAge\t\t= %4.1f years\n',(datenum(T0)-datenum(T1))/(365.25)); 128 end; 129 fprintf(fid,'\tBirthday\t= %04i-%02i-%02i %02i:%02i:%06.3f\n',T1); 130 end; 131end; 132 133if isfield(HDR,'Manufacturer') 134 fprintf(fid,'Manufacturer.\n'); 135 if isfield(HDR.Manufacturer,'Name') 136 fprintf(fid,'\tName\t\t= %s\n',HDR.Manufacturer.Name); 137 end; 138 if isfield(HDR.Manufacturer,'Model') 139 fprintf(fid,'\tModel\t\t= %s\n',HDR.Manufacturer.Model); 140 end; 141 if isfield(HDR.Manufacturer,'Version') 142 fprintf(fid,'\tVersion \t= %s\n',HDR.Manufacturer.Version); 143 end; 144 if isfield(HDR.Manufacturer,'SerialNumber') 145 fprintf(fid,'\tSerialNumber \t= %s\n',HDR.Manufacturer.SerialNumber); 146 end; 147end; 148 149 150%%%%%%%% CHANNEL DATA %%%%%%%%%%%%%%% 151if ~isfield(HDR,'AS') && isfield(HDR,'SampleRate') 152 HDR.AS.SampleRate = repmat(HDR.SampleRate,HDR.NS,1); 153end; 154if ~isfield(HDR.AS,'SPR'), 155 HDR.AS.SPR = repmat(HDR.SPR,1,HDR.NS); 156end; 157if ~isfield(HDR.AS,'SampleRate'), 158 HDR.AS.SampleRate = HDR.AS.SPR/HDR.SPR*HDR.SampleRate; 159end; 160if ~isfield(HDR,'THRESHOLD') 161 HDR.THRESHOLD = repmat(NaN,HDR.NS,2); 162end; 163if ~isfield(HDR,'PhysDimCode') 164 if isfield(HDR,'PhysDim') 165 HDR.PhysDimCode = physicalunits(HDR.PhysDim); 166 else 167 HDR.PhysDimCode = zeros(1,HDR.NS); 168 end 169end; 170if ~isfield(HDR,'LeadIdCode') 171 HDR = leadidcodexyz(HDR); 172end; 173if ~isfield(HDR,'REC') 174 HDR.REC.Impedance = repmat(NaN,HDR.NS,1); 175end; 176if ~isfield(HDR.REC,'Impedance') 177 HDR.REC.Impedance = repmat(NaN,HDR.NS,1); 178end; 179if ~isfield(HDR,'InChanSelect') 180 InChanSelect = 1:HDR.NS; 181else 182 InChanSelect = HDR.InChanSelect; 183end 184if ~isfield(HDR,'Filter') || ~isfield(HDR.Filter,'HighPass'); 185 HDR.Filter.HighPass = repmat(NaN,1,HDR.NS); 186end; 187if ~isfield(HDR.Filter,'LowPass'); 188 HDR.Filter.LowPass = repmat(NaN,1,HDR.NS); 189end; 190if ~isfield(HDR.Filter,'Notch'); 191 HDR.Filter.Notch = repmat(NaN,1,HDR.NS); 192end; 193if (HDR.NS>0); 194if length(HDR.Filter.HighPass)==1, 195 HDR.Filter.HighPass = repmat(HDR.Filter.HighPass,HDR.NS,1); 196end; 197if length(HDR.Filter.LowPass)==1, 198 HDR.Filter.LowPass = repmat(HDR.Filter.LowPass,HDR.NS,1); 199end; 200if length(HDR.Filter.Notch)==1, 201 HDR.Filter.Notch = repmat(HDR.Filter.Notch,HDR.NS,1); 202end; 203end; 204 205if ~isfield(HDR,'Cal') && isfield(HDR,'Calib') 206 Cal = ones(HDR.NS,1); 207 Cal(InChanSelect) = diag(HDR.Calib(2:end,:)); 208elseif isfield(HDR,'Cal') 209 if length(HDR.Cal)==1, 210 Cal = repmat(HDR.Cal,HDR.NS,1); 211 else 212 Cal = HDR.Cal; 213 end; 214elseif isfield(HDR,'DigMin') && isfield(HDR,'DigMax') && isfield(HDR,'PhysMin') && isfield(HDR,'PhysMax') 215 Cal = (HDR.PhysMax-HDR.PhysMin)./(HDR.DigMax-HDR.DigMin); 216else 217 Cal = repmat(NaN,1,HDR.NS); 218end; 219 220if ~isfield(HDR,'Off') && isfield(HDR,'Calib') 221 Off = zeros(HDR.NS,1); 222 Cal(InChanSelect) = diag(HDR.Calib(2:end,:)); 223elseif isfield(HDR,'Off') 224 if length(HDR.Off)==1, 225 Off = repmat(HDR.Off,HDR.NS,1); 226 else 227 Off = HDR.Off; 228 end; 229elseif isfield(HDR,'DigMin') && isfield(HDR,'DigMax') && isfield(HDR,'PhysMin') && isfield(HDR,'PhysMax') 230 Off = HDR.PhysMin - Cal.*HDR.DigMin; 231else 232 Off = repmat(NaN,1,HDR.NS); 233end; 234 235PhysDim = physicalunits(HDR.PhysDimCode); 236fprintf(fid,'\n[Channel Header]\n#No LeadId Label\tfs [Hz]\tGDFTYP\tTH- TH+ Offset Calib PhysDim HP[Hz] LP[Hz] Notch R[kOhm] x y z\n'); 237for k = 1:HDR.NS, 238 Label = HDR.Label{k}; 239 Z = HDR.REC.Impedance(k)/1000; 240 gdftyp = HDR.GDFTYP(min(length(HDR.GDFTYP),k)); 241 LP = HDR.Filter.LowPass(min(length(HDR.Filter.LowPass),k)); 242 HP = HDR.Filter.HighPass(min(length(HDR.Filter.HighPass),k)); 243 Notch = HDR.Filter.Notch(min(length(HDR.Filter.Notch),k)); 244 physdim = PhysDim(min(length(PhysDim),k)); 245 Label(Label==9)=' '; % replace TAB's because TAB's are used as field delimiter 246 if isfield(HDR.AS,'SampleRate') 247 Fs = HDR.AS.SampleRate(k); 248 else 249 Fs = HDR.SampleRate; 250 end; 251 fprintf(fid,'%3i %i\t%-9s\t%6.1f %2i %i\t%i\t%6e\t%6e %5s %6.4f %5.1f %i %5.1f %f %f %f\n',k,HDR.LeadIdCode(k),Label,Fs,gdftyp,HDR.THRESHOLD(k,1:2),Off(k),Cal(k),physdim{1},HP,LP,Notch,Z,HDR.ELEC.XYZ(k,:)); 252end; 253 254if ~isfield(HDR.EVENT,'SampleRate'); 255 HDR.EVENT.SampleRate = HDR.SampleRate; 256end; 257%%%%%%%%%% EVENTTABLE %%%%%%%%%%%%%%% 258fprintf(fid,'\n[Event Table]\n'); 259fprintf(fid,'NumberOfEvents=%i SampleRate=%f\n TYP\t POS \t date time\t',length(HDR.EVENT.POS),HDR.EVENT.SampleRate); 260if isfield(HDR.EVENT,'CHN') 261 fprintf(fid,'\tCHN\tDUR/VAL'); 262end; 263fprintf(fid,'\tDescription\n'); 264 265% use global to improve speed 266global BIOSIG_GLOBAL; 267if ~isfield(BIOSIG_GLOBAL,'ISLOADED_EVENTCODES') 268 BIOSIG_GLOBAL.ISLOADED_EVENTCODES = 0; 269end; 270if ~BIOSIG_GLOBAL.ISLOADED_EVENTCODES, 271 H=sopen('eventcodes.txt'); % if successful, it will set BIOSIG_GLOBAL.ISLOADED_EVENTCODES 272 sclose(H); 273 if ~BIOSIG_GLOBAL.ISLOADED_EVENTCODES, 274 fprintf(2,'Error: unable to load definition of EventCodes - in order to fix this, include the directory .../biosig4matlab/doc/ in your path'); 275 end 276end; 277 278 279[tmp,eIdx]=sort(HDR.EVENT.POS); % sort event in chronological order 280 281for k = eIdx(:)', 282 if any(isnan(HDR.T0)) 283 T0 = 0; 284 elseif length(HDR.T0)==1, 285 T0 = HDR.T0; 286 else 287 T0 = datenum(HDR.T0); 288 end; 289 if isfield(HDR.EVENT,'TimeStamp'); 290 t = datevec(HDR.EVENT.TimeStamp(k)); 291 else 292 t = datevec(HDR.EVENT.POS(k)/(24*3600*HDR.SampleRate)+T0); 293 end 294 fprintf(fid,'0x%04x\t%9i\t%04i-%02i-%02i %02i:%02i:%07.4f',[HDR.EVENT.TYP(k),HDR.EVENT.POS(k),t(1:6)]); 295 if isfield(HDR.EVENT,'CHN') 296 if ~isempty(HDR.EVENT.CHN) 297 fprintf(fid,'\t%i', HDR.EVENT.CHN(k)); 298 DUR = HDR.EVENT.DUR(k); 299 if (HDR.EVENT.TYP(k)~=hex2dec('7fff')) 300 fprintf(fid,'\t%i', DUR); 301 end; 302 end; 303 else 304 fprintf(fid,'\t-\t-'); 305 end; 306 307 if HDR.EVENT.TYP(k)==hex2dec('7fff'), 308 ch = HDR.EVENT.CHN(k); 309 pu = physicalunits(HDR.PhysDimCode(ch)); 310 fprintf(fid,'\t%f %s', HDR.EVENT.VAL(k), pu{1}); 311 elseif 0, 312 elseif HDR.EVENT.TYP(k)==0, 313 ; 314 elseif HDR.EVENT.TYP(k)==hex2dec('7ffe'), 315 ; 316 elseif (isfield(HDR.EVENT,'CodeDesc') && (HDR.EVENT.TYP(k) <= length(HDR.EVENT.CodeDesc))) 317 fprintf(fid,'\t%s',HDR.EVENT.CodeDesc{HDR.EVENT.TYP(k)}); 318 else 319 ix = find(HDR.EVENT.TYP(k)==BIOSIG_GLOBAL.EVENT.CodeIndex); 320 if length(ix)==1, 321 fprintf(fid,'\t%s',BIOSIG_GLOBAL.EVENT.CodeDesc{ix}); 322 end; 323 end; 324 fprintf(fid,'\n'); 325end; 326 327if fid>2, 328 fclose(fid); 329end; 330if nargout>0, 331 argout=HDR; 332end; 333 334