TEAP (Toolbox for Emotion Analysis using Physiological Signals) doc
physicalunits.m
Go to the documentation of this file.
1 function [out,scale] = physicalunits(arg1)
2 % PHYSICALUNITS converts PhysDim inte PhysDimCode and vice versa
3 % according to Annex A of FEF Vital Signs Format [1]
4 %
5 % HDR = physicalunits(HDR);
6 % adds HDR.PhysDim or HDR.PhysDimCode, if needed
7 %
8 % PhysDim = physicalunits(PhysDimCode);
9 % converts Code of PhysicalUnits into descriptive physical units
10 %
11 % PhysDimCode = physicalunits(PhysDim);
12 % converts descriptive units into Code for physical units.
13 %
14 % [..., scale] = physicalunits(...);
15 % scale contains the scaling factor of the decimal prefix
16 %
17 % see also: SLOAD, SOPEN, doc/DecimalFactors.txt, doc/units.csv
18 %
19 % Reference(s):
20 % [1] CEN/TC251/PT40 (2001)
21 % File Exchange Format for Vital Signs - Annex A
22 % [2] The Unified Code for Units of Measure (UCUM)
23 % http://aurora.regenstrief.org/UCUM/ucum.html
24 
25 
26 % This program is free software; you can redistribute it and/or
27 % modify it under the terms of the GNU General Public License
28 % as published by the Free Software Foundation; either version 3
29 % of the License, or (at your option) any later version.
30 
31 % $Id: physicalunits.m 2794 2011-10-11 08:51:36Z schloegl $
32 % Copyright (C) 2005,2008 by Alois Schloegl <a.schloegl@ieee.org>
33 % This is part of the BIOSIG-toolbox http://biosig.sf.net/
34 
35 
36 
37 global BIOSIG_GLOBAL;
38 if ~isfield(BIOSIG_GLOBAL,'ISLOADED')
39  BIOSIG_GLOBAL.ISLOADED = 0 ;
40 end;
41 if ~BIOSIG_GLOBAL.ISLOADED;
42  f=which('getfiletype.m'); % identify path to biosig
43  [p,f,e]=fileparts(f);
44  [p,f,e]=fileparts(p);
45 
46  %%%---------- Load Decimal factors ------------%%%
47  BIOSIG_GLOBAL.ISLOADED = 0 ;
48  [fid,msg] = fopen(fullfile(p,'doc','DecimalFactors.txt'),'rt','ieee-le');
49  line = fgetl(fid);
50  N1 = 0; N2 = 0;
51  while ~feof(fid),
52  if ~strncmp(line,'#',1),
53  N1 = N1 + 1;
54  [n,v,s] = str2double(line);
55  n = n(~v);
56  DecimalFactor.Code(N1,1) = n(2);
57  DecimalFactor.Cal(N1,1) = n(1);
58  s = s(~~v);
59  if any(v)
60  DecimalFactor.Name(N1,1) = s(1);
61  DecimalFactor.Prefix(N1,1) = s(2);
62  end;
63  end;
64  line = fgetl(fid);
65  end;
66  fclose(fid);
67  BIOSIG_GLOBAL.DecimalFactor = DecimalFactor;
68 
69  %%%---------- Physical units ------------%%%
70  fid = fopen(fullfile(p,'doc','units.csv'));
71  line = fgetl(fid);
72  N1 = 0; N2 = 0;
73  while ~feof(fid),
74  N2 = N2 + 1;
75  if ~strncmp(line,'#',1),
76  ix = mod(cumsum(line==char(34)),2); %% "
77  tmp = line;
78  tmp(~~ix) = ' ';
79  ix = find(tmp==',');
80  if (length(ix)~=3)
81  fprintf(2,'Warning: line (%3i: %s) not valid\n',N2,line);
82  else
83  t1 = line(1:ix(1)-1);
84  t2 = line(ix(1)+1:ix(2)-1);
85  t3 = line(ix(2)+1:ix(3)-1);
86  t4 = line(ix(3)+1:end);
87  Code = str2double(t1);
88  if ~isempty(Code)
89  N1 = N1 + 1;
90  UnitsOfMeasurement.Code(N1,1) = Code;
91  ix = min(find([t2, '[' ] == '['))-1;
92  UnitsOfMeasurement.Symbol{N1,1} = char(t2(2:ix-1));
93  end;
94  end;
95  end;
96  line = fgetl(fid);
97  end;
98  fclose(fid);
99  BIOSIG_GLOBAL.Units = UnitsOfMeasurement;
100 
101  %%%---------- Load x73-UCUM Table ------------%%%
102  fid=fopen('IEEEandUCUM.1b.txt','rt');
103  if fid>1,
104  r = char(fread(fid,[1,inf],'uint8'));
105  fclose(fid);
106  while strncmp(r,'#',1)
107  [line,r] = strtok(r,[10,13]);
108  end;
109  K1 = 1;
110  [line,r] = strtok(r,[10,13]);
111  while ~isempty(r),
112  ix = [0,find(line == 9),length(line)+1]; % tab
113  for K2 = 1:length(ix)-2,
114  if ix(K2)+2>ix(K2+1)-2,
115  tab{K1,K2} = ' ';
116  else
117  tab{K1,K2} = line(ix(K2)+2:ix(K2+1)-2);
118  end;
119  end;
120  K2 = length(ix)-1;
121  tab{K1,6} = str2double(line(ix(K2)+1:ix(K2+1)-1));
122 
123  [line,r] = strtok(r,[10,13]);
124  K1 = K1+1;
125  end;
126  BIOSIG_GLOBAL.x73_UCUM = tab;
127  end;
128 
129  BIOSIG_GLOBAL.ISLOADED = 1;
130 end;
131 
132 
133 if isstruct(arg1)
134  HDR = arg1;
135  if 0,
136  elseif isfield(HDR,'PhysDim') && isfield(HDR,'PhysDimCode')
137  [PhysDimCode,scale] = physicalunits(HDR.PhysDim);
138  if any(PhysDimCode(:)~=HDR.PhysDimCode(:))
139  warning('PhysDim and PhysDimCode differ');
140  PhysDim',HDR.PhysDim'
141  end;
142  elseif ~isfield(HDR,'PhysDim') && isfield(HDR,'PhysDimCode')
143  [HDR.PhysDim, scale] = physicalunits(HDR.PhysDimCode);
144  elseif isfield(HDR,'PhysDim') % ~isfield(HDR,'PhysDimCode')
145  [HDR.PhysDimCode,scale] = physicalunits(HDR.PhysDim);
146  elseif ~isfield(HDR,'PhysDim') && ~isfield(HDR,'PhysDimCode')
147  HDR.PhysDimCode = zeros(HDR.NS,1);
148  HDR.PhysDim = repmat({'?'},HDR.NS,1);
149  scale = ones(HDR.NS,1);
150  fprintf(HDR.FILE.stderr,'Neither PhysDim nor PhysDimCode defined in file %s\n',HDR.FileName);
151  end;
152  out = HDR;
153 
154 elseif isnumeric(arg1)
155  s = mod(arg1,32);
156  n = bitand(arg1,2^16-32);
157  scale = repmat(NaN,size(arg1));
158  PhysDim = repmat({'?'},size(arg1));
159  for k = 1:length(n);
160  if any(BIOSIG_GLOBAL.DecimalFactor.Code==s(k)),
161  t1 = BIOSIG_GLOBAL.DecimalFactor.Prefix{BIOSIG_GLOBAL.DecimalFactor.Code==s(k)};
162  ix = find(BIOSIG_GLOBAL.Units.Code==n(k));
163  if ~isempty(ix)
164  t2 = BIOSIG_GLOBAL.Units.Symbol{ix};
165  PhysDim{k} = [t1,t2];
166  scale(k) = BIOSIG_GLOBAL.DecimalFactor.Cal(BIOSIG_GLOBAL.DecimalFactor.Code==s(k));
167  end;
168  end;
169  end;
170  out = PhysDim;
171 
172 elseif ischar(arg1) || iscell(arg1)
173  if iscell(arg1)
174  N = length(arg1);
175  elseif ischar(arg1)
176  N = size(arg1,1);
177  arg1 = cellstr(arg1);
178  end;
179  j = 1:length(arg1);
180  VER = version;
181 
182  % This does not work for Octave 2.9.9 and earlier versions.
183  % Uncomment the next line to fix it. It is slower but correct.
184  [arg1,i,j] = unique(arg1);
185 
186  Code = zeros(length(arg1),1); % default value is 0 (unknown)
187  for k=1:length(arg1);
188  unit = deblank(arg1{k});
189  if length(unit)>0,
190  if (unit(1)==181), unit(1)='u'; end;
191  else
192 
193  end;
194 
195  % this lookup table contains first the most widely used
196  % physical units
197  if ~length(unit),
198  Code(k) = 0;
199  elseif strcmpi(unit,'-') % dimensionless
200  Code(k) = 512;
201  elseif strcmpi(unit,'1') % dimensionless
202  Code(k) = 512;
203  elseif strcmpi(unit,'percent')
204  Code(k) = 544;
205  elseif strcmpi(unit,'%')
206  Code(k) = 544;
207  elseif strcmpi(unit,'degree')
208  Code(k) = 736;
209  elseif strcmpi(unit,'rad')
210  Code(k) = 768;
211  elseif strcmp(unit,'Hz')
212  Code(k) = 2496;
213  elseif strcmp(unit,'l/(min*m²)')
214  Code(k) = 2848;
215  elseif strcmp(unit,'l/min')
216  Code(k) = 3072;
217  elseif strcmp(unit,'mmHg')
218  Code(k) = 3872;
219  elseif strcmp(unit,'dyne*s/cm^5')
220  Code(k) = 4128;
221  elseif strcmp(unit,'V')
222  Code(k) = 4256;
223  elseif strcmp(unit,'mV')
224  Code(k) = 4256 + 18;
225  elseif strcmp(unit,'uV')
226  Code(k) = 4256 + 19;
227  elseif strcmp(unit,'Ohm')
228  Code(k) = 4288;
229  elseif strcmp(unit,'K')
230  Code(k) = 4384;
231  elseif strcmp(unit,'°F')
232  Code(k) = 4416;
233  elseif strcmp(unit,'°C')
234  Code(k) = 6048;
235  elseif strcmp(unit,'m/s²')
236  Code(k) = 6624
237  elseif strcmp(unit,'dyne*s*m²/cm^5')
238  Code(k) = 65440;
239  elseif strcmp(unit,'l/m²')
240  Code(k) = 65472;
241  elseif strcmp(unit,'ml/m²')
242  Code(k) = 65472+18;
243  else
244  % this is the general method to determine the
245  % Physical Dimension's code
246  ix = [];
247  for k1=1:length(BIOSIG_GLOBAL.DecimalFactor.Code)
248  for k2=1:length(BIOSIG_GLOBAL.Units.Code)
249  if strcmp(unit,[BIOSIG_GLOBAL.DecimalFactor.Prefix{k1},BIOSIG_GLOBAL.Units.Symbol{k2}])
250  ix = [ix,BIOSIG_GLOBAL.Units.Code(k2) + BIOSIG_GLOBAL.DecimalFactor.Code(k1)];
251  end;
252  end;
253  end;
254 
255  %%%%% usis x73-UCUM table, col 3 and 4 %%%%
256  ix2 = [];
257  ix3 = [];
258  if isfield(BIOSIG_GLOBAL,'x73_UCUM')
259  for k1=1:length(BIOSIG_GLOBAL.DecimalFactor.Code)
260  for k2=1:size(BIOSIG_GLOBAL.x73_UCUM,1)
261  if strcmpi(unit,[BIOSIG_GLOBAL.DecimalFactor.Prefix{k1},BIOSIG_GLOBAL.x73_UCUM{k2,3}])
262  ix2 = [ix2,BIOSIG_GLOBAL.x73_UCUM{k2,6} + BIOSIG_GLOBAL.DecimalFactor.Code(k1)];
263  end;
264  if strcmpi(unit,[BIOSIG_GLOBAL.DecimalFactor.Prefix{k1},BIOSIG_GLOBAL.x73_UCUM{k2,4}])
265  ix3 = [ix3,BIOSIG_GLOBAL.x73_UCUM{k2,6} + BIOSIG_GLOBAL.DecimalFactor.Code(k1)];
266  end;
267  end;
268  end;
269  end;
270 
271  if length(ix)==1,
272  Code(k) = ix;
273  elseif length(ix)>1,
274  ix = ix(~mod(ix,32)); % select those with no PreFix (code offset = 0)
275  if length(ix)==1,
276  Code(k) = ix;
277  elseif sum(ix<64000)==1,
278  Code(k) = ix(ix<64000);
279  else
280  warning('ambigous physical unit')
281  end;
282  elseif length(ix2)==1,
283  Code(k) = ix2;
284  elseif length(ix3)==1,
285  Code(k) = ix3;
286  end;
287  end;
288 
289  end;
290  Code = Code(j);
291  scale = repmat(NaN,size(Code));
292  for k = 1:numel(Code);
293  scale(k) = BIOSIG_GLOBAL.DecimalFactor.Cal(BIOSIG_GLOBAL.DecimalFactor.Code==bitand(Code(k),31));
294  end;
295  out = Code;
296 
297 end;
physicalunits
function physicalunits(in arg1)
str2double
function str2double(in s, in cdelim, in rdelim, in ddelim)
getfiletype
function getfiletype(in arg1)