attachment:phys_noise.m of PhysNoise - MRC CBU Imaging Wiki
location: attachment:phys_noise.m of PhysNoise

Attachment 'phys_noise.m'

Download

   1 function [Y, T] = phys_noise(varargin)
   2 %PHYS_NOISE Summary of this function goes here
   3 %   Detailed explanation goes here
   4 
   5 ppg_file   = varargin{1};
   6 dic_folder = varargin{2};
   7 TR         = varargin{4};
   8 Hz         = varargin{10};
   9 
  10 %% start
  11 P.TR        = TR; % Acquisition time (for working around dummy scans)
  12 P.EndClip   = 1000; % Always seems to take a second and change to finish
  13 P.StartClip = 0;    % Some systems have to have a pause between record onset and gradient onset
  14 P.Hz        = Hz;   % Sampling Frequency
  15 P.StartJump = 0;    % Number of shift samples to adjust at the beginning of the series
  16 P.FirstScan = 1;
  17 P.TickTime  = 1000/P.Hz;
  18 [Y,T,P] = read_ppg(ppg_file,P);
  19 
  20 % get the start and end of scanning scanning
  21 % start - first series folder and first dicom
  22 % end   - last series fold and last dicom
  23 
  24 % get series folders
  25 ser_folder = dic_folder(1:strfind(dic_folder, '/Series'));
  26 dce_f = dir(ser_folder);
  27 dc1_folder = fullfile(ser_folder,dce_f(3).name);
  28 dce_folder = fullfile(ser_folder,dce_f(end).name);
  29 
  30 dc1_files = fullfl(dc1_folder,'1.3','dcm');
  31 dce_files = fullfl(dce_folder,'1.3','dcm');
  32 dc1_file  = dc1_files{1};
  33 dce_file  = dce_files{end};
  34 dc1_hdr   = spm_dicom_headers(dc1_file, false);
  35 dce_hdr   = spm_dicom_headers(dce_file, false);
  36 mri_start = dc1_hdr{1}.AcquisitionTime;
  37 mri_stop  = dce_hdr{1}.ContentTime;
  38 mri_dur   = mri_stop - mri_start;
  39 disp(['--- Total MRI time ---']);
  40 disp(['MRI start        : ' secs2hms(mri_start)]);
  41 disp(['MRI stop         : ' secs2hms(mri_stop)]);
  42 disp(['MRI duration     : ' secs2hms(mri_dur)]);
  43 
  44 % load dicom headers
  45 dicoms = fullfl(dic_folder,'1.3','dcm');
  46 dicoms = dicoms(P.FirstScan:end);
  47 d_1st = 1;
  48 d_end = size(dicoms,1);
  49 hdr_1 = spm_dicom_headers(dicoms{d_1st}, false);
  50 hdr_e = spm_dicom_headers(dicoms{d_end}, false);
  51 
  52 % dicom start (in seconds since midnight)
  53 d_start = hdr_1{1}.AcquisitionTime;
  54 d_stop  = hdr_e{1}.ContentTime;
  55 
  56 % ppg start
  57 p_start = P.MRIStartTime/1000; % secs
  58 p_stop  = P.MRIStopTime/1000;  % secs
  59 p_dur   = p_stop - p_start;    % secs
  60 offset  = d_start - p_start;   % secs
  61 i_s = ceil(offset*P.Hz);       % secs * Hz = indices
  62 i_e = ceil((offset+(d_end*P.TR/1000))*P.Hz);
  63 %i_e = ceil((d_stop - p_start)*P.Hz);
  64 
  65 disp(['Phys log start   : ' secs2hms(p_start)]);
  66 disp(['Phys log stop    : ' secs2hms(p_stop)]);
  67 disp(['Phys log duration: ' secs2hms(p_dur)]);
  68 disp(['Freq estimate    : ' num2str(size(Y,2)/p_dur) 'hz, Freq used: ' num2str(P.Hz) 'hz'])
  69 disp(['--- Run information ---']);
  70 disp(['Number of dicoms : ' num2str(d_end)]);
  71 disp(['First dicom      : ' secs2hms(d_start)]);
  72 disp(['Last dicom       : ' secs2hms(d_stop)]);
  73 disp(['Phys-dicom       : ' secs2hms(d_start-p_start)]);
  74 disp(['Phys indices     : ' num2str(i_s) ' ... ' num2str(i_e)]);
  75 
  76 % extract ppg data pertaining to this run
  77 Y = Y(i_s:i_e);
  78 T = T(i_s:i_e);
  79 T = T - T(1);
  80 disp(['Run duration from dicoms      : ' num2str((size(Y,2).*P.TickTime)/1000/60) ' mins']);
  81 disp(['Phys. data for this run       : ' num2str((T(end)-T(1))/60) ' mins']);
  82 
  83 % check if there is any data in Y
  84 if numel(unique(Y))==1
  85     disp('-- ERROR --');
  86     disp('The physiological signal extracted for this time period is completely flat!');
  87     disp(['Check the file ' ppg_file]);
  88     disp('for the time period reported above');
  89     disp('Noise regressor cannot be estimated.');
  90     disp('This might be because your recording equipment was detached during this scanning period');
  91     error('Exiting ..');    
  92 end
  93 
  94 % saving
  95 [fpath fname fext] = fileparts(ppg_file);
  96 save(fullfile(fpath,[fname '.mat']),'Y','T','P');
  97 
  98 function [signal,time,P] = read_ppg(pulsefile,P)
  99 
 100 fclose('all');
 101 
 102 fid=fopen(pulsefile);
 103 ignore=textscan(fid,'%s',4); %Ignore first 4 values.
 104 
 105 data   = textscan(fid,'%u16'); %Read data until end of u16 data.
 106 footer = textscan(fid,'%s');   %Read in remaining data (time stamps and statistics).
 107 
 108 if ~size(footer{1},1)
 109     disp('No footer found in the log file!');
 110     disp('Hence, the start of the logging is unknown');
 111     disp('and match with dicoms cannot be calculated.');
 112     disp('This might indicate that the equipment was switched off unexpectedly.');
 113     error('Exiting..');
 114 end
 115 
 116 %Get time stamps from footer:
 117 for n=1:size(footer{1},1)
 118     if strcmp(footer{1}(n),'LogStartMDHTime:')  %log start time
 119         P.LogStartTime=str2num(footer{1}{n+1});
 120     end
 121     if strcmp(footer{1}(n),'LogStopMDHTime:')   %log stop time
 122         P.LogStopTime=str2num(footer{1}{n+1});
 123     end
 124     if strcmp(footer{1}(n),'LogStartMPCUTime:') %scan start time
 125         P.MRIStartTime=str2num(footer{1}{n+1});
 126     end
 127     if strcmp(footer{1}(n),'LogStopMPCUTime:')  %scan stop time
 128         P.MRIStopTime=str2num(footer{1}{n+1});
 129     end
 130 end
 131 
 132 % Remove the systems own evaluation of triggers.
 133 t_on  = find(data{1} == 5000);  % System uses identifier 5000 as trigger ON
 134 t_off = find(data{1} == 5003);  % System uses identifier 5003 as trigger OFF
 135 
 136 % Filter the trigger markers from the data
 137 Hz = P.Hz;
 138 data_t=transpose(1:length(data{1}));
 139 indx = setdiff(data_t(:),union(t_on,t_off)); %Note: depending on when the scan ends, the last size(t_off)~=size(t_on).
 140 signal = data{1}(indx);
 141 time = (1:length(signal))./Hz;
 142 
 143 % Clip the time series to begin and end with the scan.
 144 if P.TR < 1000
 145   start = P.StartClip*(Hz/1000);
 146   stop  = length(signal) - Hz*floor([length(signal) - EndClip*(Hz/1000)]/Hz);
 147 else
 148   start = P.StartClip*(Hz/1000)+Hz/2;
 149   stop  = P.EndClip*(Hz/1000)+mod(length(signal(1:end)),Hz)+ Hz/2;
 150   %stop  = length(signal) - Hz*floor([length(signal) - P.EndClip*(Hz/1000)]/Hz) + Hz/2;
 151 end;
 152 
 153 % Reset vectors;
 154 signal = double(signal(start+1-P.StartJump:end-stop-P.StartJump)');
 155 time = time(start+1-P.StartJump:end-stop-P.StartJump);
 156 time = time(:)-time(1);
 157 
 158 function [Y,T,P] = read_pulsef(pulsefile)
 159 
 160 [fid, emsg]  = fopen(pulsefile);
 161 
 162 if fid==-1
 163     error(emsg);
 164 end
 165 
 166 tline = fgetl(fid);
 167 C = [];
 168 
 169 while ischar(tline)
 170     C{end+1,1} = tline;
 171     tline = fgetl(fid);
 172 end
 173 fclose(fid);
 174 
 175 Y = str2num(C{1,1});
 176 p = Y(1:5); % first 5 values are parameters
 177 Y = Y(6:end); % resize Y, starting with the 6th value of the first line are the voltage values themselves that reflect the pulse ox.
 178 
 179 P.TickTime   = p(3); %time (in msec) between subsequent measurements
 180 P.StartMDH   = get_timeval(C{11,1});
 181 P.StopMDH    = get_timeval(C{12,1});
 182 P.StartMPCU  = get_timeval(C{13,1});
 183 P.StopMPCU   = get_timeval(C{14,1});
 184 
 185 function timeval = get_timeval(ccell)
 186 [~, timeval] = strtok(ccell);
 187 timeval = str2num(rmwhite(timeval));

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2013-06-26 11:10:01, 29.2 KB) [[attachment:aR2_diff_ov_10-1.jpg]]
  • [get | view] (2013-06-26 11:09:48, 32.5 KB) [[attachment:aR2_diff_ov_11-1.jpg]]
  • [get | view] (2013-06-26 11:09:43, 30.3 KB) [[attachment:aR2_diff_ov_12-1.jpg]]
  • [get | view] (2013-06-26 11:08:33, 27.7 KB) [[attachment:aR2_diff_ov_2-1.jpg]]
  • [get | view] (2013-06-26 11:08:41, 21.9 KB) [[attachment:aR2_diff_ov_3-1.jpg]]
  • [get | view] (2013-06-26 11:08:49, 26.1 KB) [[attachment:aR2_diff_ov_4-1.jpg]]
  • [get | view] (2013-06-26 11:08:55, 25.7 KB) [[attachment:aR2_diff_ov_5-1.jpg]]
  • [get | view] (2013-06-26 11:09:03, 23.9 KB) [[attachment:aR2_diff_ov_6-1.jpg]]
  • [get | view] (2013-06-26 11:09:10, 25.8 KB) [[attachment:aR2_diff_ov_7-1.jpg]]
  • [get | view] (2013-06-26 11:09:17, 29.4 KB) [[attachment:aR2_diff_ov_8-1.jpg]]
  • [get | view] (2013-06-26 11:09:22, 31.5 KB) [[attachment:aR2_diff_ov_9-1.jpg]]
  • [get | view] (2013-06-26 10:55:26, 20.3 KB) [[attachment:ov-aR2.jpg]]
  • [get | view] (2013-06-26 10:46:45, 6.3 KB) [[attachment:phys_noise.m]]
  • [get | view] (2013-06-26 11:22:46, 123.3 KB) [[attachment:r2diff_ov.jpg]]
  • [get | view] (2013-06-26 11:22:38, 124.4 KB) [[attachment:r2diff_rm.jpg]]
  • [get | view] (2013-06-26 10:55:21, 16.0 KB) [[attachment:rm-aR2.jpg]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.