zoukankan      html  css  js  c++  java
  • edfread源码

      1 function [hdr, record] = edfread(fname, varargin)
      2 % Read European Data Format file into MATLAB
      3 %
      4 % [hdr, record] = edfread(fname)
      5 %         Reads data from ALL RECORDS of file fname ('*.edf'). Header
      6 %         information is returned in structure hdr, and the signals
      7 %         (waveforms) are returned in structure record, with waveforms
      8 %         associated with the records returned as fields titled 'data' of
      9 %         structure record.
     10 %
     11 % [...] = edfread(fname, 'assignToVariables', assignToVariables)
     12 %         Triggers writing of individual output variables, as defined by
     13 %         field 'labels', into the caller workspace.
     14 %
     15 % [...] = edfread(...,'desiredSignals',desiredSignals)
     16 %         Allows user to specify the names (or position numbers) of the
     17 %         subset of signals to be read. |desiredSignals| may be either a
     18 %         string, a cell array of comma-separated strings, or a vector of
     19 %         numbers. (Default behavior is to read all signals.)
     20 %         E.g.:
     21 %         data = edfread(mydata.edf,'desiredSignals','Thoracic');
     22 %         data = edfread(mydata.edf,'desiredSignals',{'Thoracic1','Abdominal'});
     23 %         or
     24 %         data = edfread(mydata.edf,'desiredSignals',[2,4,6:13]);
     25 %
     26 % FORMAT SPEC: Source: http://www.edfplus.info/specs/edf.html SEE ALSO:
     27 % http://www.dpmi.tu-graz.ac.at/~schloegl/matlab/eeg/edf_spec.htm
     28 %
     29 % The first 256 bytes of the header record specify the version number of
     30 % this format, local patient and recording identification, time information
     31 % about the recording, the number of data records and finally the number of
     32 % signals (ns) in each data record. Then for each signal another 256 bytes
     33 % follow in the header record, each specifying the type of signal (e.g.
     34 % EEG, body temperature, etc.), amplitude calibration and the number of
     35 % samples in each data record (from which the sampling frequency can be
     36 % derived since the duration of a data record is also known). In this way,
     37 % the format allows for different gains and sampling frequencies for each
     38 % signal. The header record contains 256 + (ns * 256) bytes.
     39 %
     40 % Following the header record, each of the subsequent data records contains
     41 % 'duration' seconds of 'ns' signals, with each signal being represented by
     42 % the specified (in the header) number of samples. In order to reduce data
     43 % size and adapt to commonly used software for acquisition, processing and
     44 % graphical display of polygraphic signals, each sample value is
     45 % represented as a 2-byte integer in 2's complement format. Figure 1 shows
     46 % the detailed format of each data record.
     47 %
     48 % DATA SOURCE: Signals of various types (including the sample signal used
     49 % below) are available from PHYSIONET: http://www.physionet.org/
     50 %
     51 %
     52 % % EXAMPLE 1:
     53 % % Read all waveforms/data associated with file 'ecgca998.edf':
     54 %
     55 % [header, recorddata] = edfRead('ecgca998.edf');
     56 %
     57 % % EXAMPLE 2:
     58 % % Read records 3 and 5, associated with file 'ecgca998.edf':
     59 %
     60 % header = edfRead('ecgca998.edf','AssignToVariables',true);
     61 % % Header file specifies data labels 'label_1'...'label_n'; these are
     62 % % created as variables in the caller workspace.
     63 %
     64 % Coded 8/27/09 by Brett Shoelson, PhD
     65 % brett.shoelson@mathworks.com
     66 % Copyright 2009 - 2012 MathWorks, Inc.
     67 %
     68 % Modifications:
     69 % 5/6/13 Fixed a problem with a poorly subscripted variable. (Under certain
     70 % conditions, data were being improperly written to the 'records' variable.
     71 % Thanks to Hisham El Moaqet for reporting the problem and for sharing a
     72 % file that helped me track it down.)
     73 % 
     74 % 5/22/13 Enabled import of a user-selected subset of signals. Thanks to
     75 % Farid and Cindy for pointing out the deficiency. Also fixed the import of
     76 % signals that had "bad" characters (spaces, etc) in their names.
     77 
     78 % HEADER RECORD
     79 % 8 ascii : version of this data format (0)
     80 % 80 ascii : local patient identification
     81 % 80 ascii : local recording identification
     82 % 8 ascii : startdate of recording (dd.mm.yy)
     83 % 8 ascii : starttime of recording (hh.mm.ss)
     84 % 8 ascii : number of bytes in header record
     85 % 44 ascii : reserved
     86 % 8 ascii : number of data records (-1 if unknown)
     87 % 8 ascii : duration of a data record, in seconds
     88 % 4 ascii : number of signals (ns) in data record
     89 % ns * 16 ascii : ns * label (e.g. EEG FpzCz or Body temp)
     90 % ns * 80 ascii : ns * transducer type (e.g. AgAgCl electrode)
     91 % ns * 8 ascii : ns * physical dimension (e.g. uV or degreeC)
     92 % ns * 8 ascii : ns * physical minimum (e.g. -500 or 34)
     93 % ns * 8 ascii : ns * physical maximum (e.g. 500 or 40)
     94 % ns * 8 ascii : ns * digital minimum (e.g. -2048)
     95 % ns * 8 ascii : ns * digital maximum (e.g. 2047)
     96 % ns * 80 ascii : ns * prefiltering (e.g. HP:0.1Hz LP:75Hz)
     97 % ns * 8 ascii : ns * nr of samples in each data record
     98 % ns * 32 ascii : ns * reserved
     99 
    100 % DATA RECORD
    101 % nr of samples[1] * integer : first signal in the data record
    102 % nr of samples[2] * integer : second signal
    103 % ..
    104 % ..
    105 % nr of samples[ns] * integer : last signal
    106 
    107 if nargin > 5
    108     error('EDFREAD: Too many input arguments.');
    109 end
    110 
    111 if ~nargin
    112     error('EDFREAD: Requires at least one input argument (filename to read).');
    113 end
    114 
    115 [fid,msg] = fopen(fname,'r');
    116 if fid == -1
    117     error(msg)
    118 end
    119 
    120 assignToVariables = false; %Default
    121 targetSignals = []; %Default
    122 for ii = 1:2:numel(varargin)
    123     switch lower(varargin{ii})
    124         case 'assigntovariables'
    125             assignToVariables = varargin{ii+1};
    126         case 'targetsignals'
    127             targetSignals = varargin{ii+1};
    128         otherwise
    129             error('EDFREAD: Unrecognized parameter-value pair specified. Valid values are ''assignToVariables'' and ''targetSignals''.')
    130     end
    131 end
    132 
    133 
    134 % HEADER
    135 hdr.ver        = str2double(char(fread(fid,8)'));
    136 hdr.patientID  = fread(fid,80,'*char')';
    137 hdr.recordID   = fread(fid,80,'*char')';
    138 hdr.startdate  = fread(fid,8,'*char')';% (dd.mm.yy)
    139 % hdr.startdate  = datestr(datenum(fread(fid,8,'*char')','dd.mm.yy'), 29); %'yyyy-mm-dd' (ISO 8601)
    140 hdr.starttime  = fread(fid,8,'*char')';% (hh.mm.ss)
    141 % hdr.starttime  = datestr(datenum(fread(fid,8,'*char')','hh.mm.ss'), 13); %'HH:MM:SS' (ISO 8601)
    142 hdr.bytes      = str2double(fread(fid,8,'*char')');
    143 reserved       = fread(fid,44);
    144 hdr.records    = str2double(fread(fid,8,'*char')');
    145 hdr.duration   = str2double(fread(fid,8,'*char')');
    146 % Number of signals
    147 hdr.ns    = str2double(fread(fid,4,'*char')');
    148 for ii = 1:hdr.ns
    149     hdr.label{ii} = regexprep(fread(fid,16,'*char')','W','');
    150 end
    151 
    152 if isempty(targetSignals)
    153     targetSignals = 1:numel(hdr.label);
    154 elseif iscell(targetSignals)||ischar(targetSignals)
    155     targetSignals = find(ismember(hdr.label,regexprep(targetSignals,'W','')));
    156 end
    157 if isempty(targetSignals)
    158     error('EDFREAD: The signal(s) you requested were not detected.')
    159 end
    160 
    161 for ii = 1:hdr.ns
    162     hdr.transducer{ii} = fread(fid,80,'*char')';
    163 end
    164 % Physical dimension
    165 for ii = 1:hdr.ns
    166     hdr.units{ii} = fread(fid,8,'*char')';
    167 end
    168 % Physical minimum
    169 for ii = 1:hdr.ns
    170     hdr.physicalMin(ii) = str2double(fread(fid,8,'*char')');
    171 end
    172 % Physical maximum
    173 for ii = 1:hdr.ns
    174     hdr.physicalMax(ii) = str2double(fread(fid,8,'*char')');
    175 end
    176 % Digital minimum
    177 for ii = 1:hdr.ns
    178     hdr.digitalMin(ii) = str2double(fread(fid,8,'*char')');
    179 end
    180 % Digital maximum
    181 for ii = 1:hdr.ns
    182     hdr.digitalMax(ii) = str2double(fread(fid,8,'*char')');
    183 end
    184 for ii = 1:hdr.ns
    185     hdr.prefilter{ii} = fread(fid,80,'*char')';
    186 end
    187 for ii = 1:hdr.ns
    188     hdr.samples(ii) = str2double(fread(fid,8,'*char')');
    189 end
    190 for ii = 1:hdr.ns
    191     reserved    = fread(fid,32,'*char')';
    192 end
    193 hdr.label = hdr.label(targetSignals);
    194 hdr.label = regexprep(hdr.label,'W','');
    195 hdr.units = regexprep(hdr.units,'W','');
    196 disp('Step 1 of 2: Reading requested records. (This may take a few minutes.)...');
    197 if nargout > 1 || assignToVariables
    198     % Scale data (linear scaling)
    199     scalefac = (hdr.physicalMax - hdr.physicalMin)./(hdr.digitalMax - hdr.digitalMin);
    200     dc = hdr.physicalMax - scalefac .* hdr.digitalMax;
    201     
    202     % RECORD DATA REQUESTED
    203     tmpdata = struct;
    204     for recnum = 1:hdr.records
    205         for ii = 1:hdr.ns
    206             % Read or skip the appropriate number of data points
    207             if ismember(ii,targetSignals)
    208                 % Use a cell array for DATA because number of samples may vary
    209                 % from sample to sample
    210                 tmpdata(recnum).data{ii} = fread(fid,hdr.samples(ii),'int16') * scalefac(ii) + dc(ii);
    211             else
    212                 fseek(fid,hdr.samples(ii)*2,0);
    213             end
    214         end
    215     end
    216     hdr.units = hdr.units(targetSignals);
    217     hdr.physicalMin = hdr.physicalMin(targetSignals);
    218     hdr.physicalMax = hdr.physicalMax(targetSignals);
    219     hdr.digitalMin = hdr.digitalMin(targetSignals);
    220     hdr.digitalMax = hdr.digitalMax(targetSignals);
    221     hdr.prefilter = hdr.prefilter(targetSignals);
    222     hdr.transducer = hdr.transducer(targetSignals);
    223     
    224     record = zeros(numel(hdr.label), hdr.samples(1)*hdr.records);
    225     % NOTE: 5/6/13 Modified for loop below to change instances of hdr.samples to
    226     % hdr.samples(ii). I think this underscored a problem with the reader.
    227     
    228     disp('Step 2 of 2: Parsing data...');
    229     recnum = 1;
    230     for ii = 1:hdr.ns
    231         if ismember(ii,targetSignals)
    232             ctr = 1;
    233             for jj = 1:hdr.records
    234                 try
    235                     record(recnum, ctr : ctr + hdr.samples(ii) - 1) = tmpdata(jj).data{ii};
    236                 end
    237                 ctr = ctr + hdr.samples(ii);
    238             end
    239             recnum = recnum + 1;
    240         end
    241     end
    242     hdr.ns = numel(hdr.label);
    243     hdr.samples = hdr.samples(targetSignals);
    244 
    245     if assignToVariables
    246         for ii = 1:numel(hdr.label)
    247             try
    248                 eval(['assignin(''caller'',''',hdr.label{ii},''',record(ii,:))'])
    249             end
    250         end
    251         record = [];
    252     end
    253 end
    254 fclose(fid);
  • 相关阅读:
    nginx正则配置解释和fastadmin
    Centos7中systemctl命令详解
    layer的iframe层的传参和回参
    centOS下jenkins
    centos下nginx安装和配置
    python文件目录练习题【一】
    python正则模块re使用案例
    python字符串常用方法
    Swoole的多进程模块
    swoole学习
  • 原文地址:https://www.cnblogs.com/myohao/p/matlab.html
Copyright © 2011-2022 走看看