Cardio-pulmonary activity is a source of noise in the BOLD fMRI signal. Physiologic recording obtained at the time of scanning may be used to create covariates to model and remove this noise. This improves model fits and statistical power in general, and is crucial for inference regarding resting state correlations 1)
A paper by Timothy Verstynen describes the rationale and technique for pulse-ox regression:
Timothy has produced a MATLAB toolbox called PhLEM for the analysis of physiologic data in neuroimaging. The output of the Exvolt routine may be used as input for PhLEM.
There is a detailed description of physiological artifact removal on Chris Rorden's Neuropsychology Lab website.
Corrections regarding the alignment of the DICOM time-stamp were kindly provided by Chris Rorden, based upon information from Brian M. Dale of Siemens.
Pulse oximetry is recorded using a Bluetooth enabled, wireless recording device that clips to the index finger of the subject. The device is stored on a rack behind the monitor of the console station for HUP6.
The set-up for a subject is as follows:
Recording is initiated from the HUP6 control console. First, enter “Advanced User” mode:
xxxxxx
This makes available the Windows “Run…” command from the Start menu. In the “Run…” entry box, type telnet mpcu
. This brings up the telnet window. Type fMenu
which brings up the text-based MPCU applications menu. Menu selections will then be selected by number. Choose PMU…
then Signal Logging…
then start PULS
. You will be asked to enter a logfile name. Use subject initials surrounding date of study, and then the scan number (e.g., L091009B_1
). Remember to turn off logging when the functional scanning is done using the stop PULS
menu item.
When the scanning session is complete, use the PUP6 computer to burn a single DVD that has both the DICOM files from the study as well as the PMU logfile (which is stored in c:\MedCom\log
).
The resulting data files are stored in c:\MedCom\log
. The log-file will have the name assigned during the set-up process (e.g., L101209B_pulse) with the suffix “.puls”. This is a text file, with the following structure:
1 2 40 280 1915 1708 1531 1340 1045 ... ECG Freq Per: 0 0 PULS Freq Per: 72 823 RESP Freq Per: 0 0 EXT Freq Per: 0 0 ECG Min Max Avg StdDiff: 0 0 0 0 PULS Min Max Avg StdDiff: 355 1646 795 5 RESP Min Max Avg StdDiff: 0 0 0 0 EXT Min Max Avg StdDiff: 0 0 0 0 NrTrig NrMP NrArr AcqWin: 0 0 0 0 LogStartMDHTime: 36632877 LogStopMDHTime: 39805825 LogStartMPCUTime: 36632400 LogStopMPCUTime: 39804637
The first five values of the first line are the parameters of the acquisition. The third of these is related to the “ticktime”, which is the time (in msec) between subsequent measurements, although the exact relationship is still being determined. Starting with the 6th value of the first line are the voltage values themselves that reflect the pulse ox. Note that the output is in voltage, not absolute SpO2 level (e.g., 98% saturation).
The sampling frequency for pulse-ox data is 50 Hz. Equivalently, a sample is acquired every 20 msecs.
Within the vector of voltage values are “trigger” events from the scanner. These are entered as 5000
(for trigger on) and 5003
(for trigger off). These values need to be stripped out of the vector. There will occasionally be extra values at the end of the voltage vector as final values in the buffer will be written to the file after the logging is stopped. This can result in the vector length being slightly longer than would be predicted from the log start and stop times described below.
The subsequent lines provide other parameters. Most relevant are the Log Start and Stop times for the MDH and MPCU. These log times indicate the time at which pulse-ox recording was started and stopped. That is, the first pulse-ox value in the first line of the data file was acquired at the LogStart time. The MPCU values provide time-stamps derived from the clock within the PMU recording system. The MDH values are time-stamps derived from the clock in the scanner, which is the same clock used to provide time-stamps for DICOM images. The MDH values are therefore preferred for synchronization of the DICOM images with the physiologic recording log.
The DICOM files and the MPCU log file both contain time tags. These time tags are derived from the same clock, but are expressed in different formats.
Each DICOM file records the time of image acquisition in the DICOM header at (0008,0032), and typically as the file name as well. The time recorded is start point of the acquisition. For example, an EPI image acquired over 3 seconds will be stamped with a time label corresponding to the very beginning of the image acquisition. An example DICOM time stamp is:
dicomImageTime = 102907.165000
ticks
or, tenths of a millisecond (in this case: 1650). The trailing two zeros are ignored.The time stamps in the MPCU log-file are in terms of msecs since midnight. An example time stamp is:
MPCU log time = 37747165
The two example time formats can be shown to be equivalent:
37747165 = (10 hours * 60 mins/hour * 60 secs/min * 1000 msecs/sec) + (29 mins * 60 * 1000) + (07 secs * 1000) + (1650 ticks / 10 ticks/msec)
In this example, the next point is at 37747165 + 20 and the next one at 37747165 + 2 * 20 and so on.
Another way to relate the physio values to simultaneously collected DICOM images is used by Timothy Verstynen. He uses only the vector of voltage physio values. Within these are the scanner trigger flags (5000
) that indicate the start of an image acquisition. He assumes that the first flag corresponds with the time of onset of the first image volume. He then extracts a vector of physio voltage values equal in temporal length (as one knows the sampling frequency) to the length of the time of image acquisition. Therefore, he does not make use of the MPCU, MDH or the DICOM time stamps.
Covariates generated from the physiologic data and corresponding to functional image acquisitions may be useful to remove the effects of physiologic noise.
Functional images are typically acquired as a set of slices during a TR. During image processing, slice acquisition correction shifts the time-series data from a set of functional images so that each slice has the functional data that would have been obtained had the image acquisition taken place all at once at the start of the TR.
For this reason, covariates generated from the physiologic data span a period corresponding to the start time of acquisition of the first functional image until the start time of acquisition of the last functional image. In other words, after slice timing correction, the DICOM image time-series is treated as if each volume were acquired instantaneously, with a delay equal to the TR between volume acquisitions.
Dongbo Hu (dongbo.hu@gmail.com) has written a C, command-line program, called Exvolt, to extract the voltage values for a given set of DICOM images:
<WRAP download round box 200px center>Download
Exvolt software</WRAP>
Building the executable from scratch requires the VoxBo lib
directory, which supports reading DICOM headers and writing out text files. The usage is:
./exvolt [--end] [--mpcu] <dicom_dir> <physio_log_file> <output_filename>
(current path: /home/dhu/cpp/physio/release/exvolt)
LogStartMDHTime
and LogStopMDHTime
; these determine the time-range of the physiological data. The range of DICOM time-stamps will be checked to ensure that the DICOM images were collected within the time spanned by the pulse-ox file. The pulse-ox values will then be extracted from the physio file for the time-range defined by the DICOM time-stamps, and saved in VoxBo REF
file format.LogStartMPCUTime
and LogStopMPCUTime
labels are used to define the time window of voltage values, instead of MDH. The MDH time-stamp values are to be preferred as they are derived from the same clock used to time-stamp the DICOM images..pmu
log file produced by the PMU during scanning.ref
file (a carriage return-delimited text file of values) with a header that includes the execution parametersNotes regarding the operation of the code:
dicom_start_time_offset = dicom_start_time - LogStartMPCUTime start_idx = ceil( dicom_start_time_offset / ticktime ) end_idx = floor( (dicom_stop_time - log_start_time) / ticktime )
Timothy Verstynen has collected physio data in concert with EPI images on his Siemens 3T scanner. His pulse-sequence is specially modified to automatically start and stop physio acquisition along with image acquisition. In July 2010 he compared the pulse-ox time-series generated with Exvolt to that obtained using his code. He found a consistent 20 sample (1 second) delay of the Exvolt results compared to the “Gold Standard” output of his code. In his analysis of his data, he found that a shift of the pulse-ox signal back in time by 340 msecs resulted in the best match with the brain signal. This was attributed to differences in arterial length between the finger where the pulse-ox was recorded and the cerebral vasculature.
We have subsequently analyzed both human and canine data using pulse-ox covariates. We have found that the phase-based regressors are equally effective in modeling physiologic variance regardless of temporal lag off-sets. This was demonstrated by shifting the raw pulse-ox time-series in 100 msec increments forwards and backwards in time up to 1000 msecs and then generating down-sampled covariates. Regardless of the shift, essentially the same variance was explained in each voxel by the combined sine and cosine regressors. This suggests that the phase relationship between the imaging data and physiologic data need only be roughly specified.
After running Exvolt to convert each .puls
data-file into a .ref
file, a Matlab(TM) coded program (PulseComplete) will take this output and return a collection of regressors which can then be implemented into the GLM.
PulseComplete allows for a user defined TR length as well as if a single, aggregated (concatenated output between all .ref files) or multiple split (individual outputs for each .ref file) is desired.
<WRAP info round box 200px center>Download
Source code for PulseComplete</WRAP>
Using PulseComplete from the command-line:
PulseComplete('desiredname.ref','outputtype',TR,heartrate,'file1',TRtotal1'file2',TRtotal2,....)
Where the first parameter is the desired name suffix, 'outputtype' is either 'single', for a single, aggregated output, 'multi' for multiple, separate outputs, or 'both' if both types are desired. TR is the TR interval in seconds, heartrate is the desired heart rate normal range, with 0 or 'high' for high heart rate (>100) or 1 or 'low' for low heart rate (<100), and finally followed by the files in series. After each file the total TR count must be included NOTE: If a given file is missing, ' (space) ' must be entered as a place holder, followed by its TR total count, as demonstrated below:
PulseComplete('example.ref','single',TR,'high','file1',150,'file2',150,' ',150,'file4',150,' ',150,' ',150,'file7',150....)
From the Siemens Physiological Monitoring Unit (PMU) technical manual: How to save the Siemens Physiologic Monitoring Unit (PMU) data to a file. The actual menu items on the scanner system may have different numbers. (User supplied responses are shown in italics)
+++++++++++++++++++++++++++++++++++++++++++ Menu V1.2 ++++ + / MPCU Applikations Menu ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + 1 - BGT-MMC Pruefung ... + 2 - PCI Karte/Treiber ... + 3 - Kommunikation zu den DSPs ... + 4 - PMU ... + 5 - Trace Utilities ... + 6 - VxWorks System Info ... + ++++++++++++++++++++++++++++++++++++++++++++++ h=Help ++++ Select number [1-6]:
+++++++++++++++++++++++++++++++++++++++++++ Menu V1.2 ++++ + /4/ PMU ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + 1 - Kommandos zum Frontend ... + 2 - Debugausgaben steuern ... + 3 - Signal Logging ... + ++++++++++++++++++++++++++++++++++++++++++++++ h=Help ++++ Select number [1-3]:
+++++++++++++++++++++++++++++++++++++++++++ Menu V1.2 ++++ + /4/3/ Signal Logging ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + 1 - start ECG + 2 - stop ECG + 3 - start RESP + 4 - stop RESP + 5 - start PULS + 6 - stop PULS + 7 - start EXT + 8 - stop EXT + 9 - start all signals + 10 - stop all signals + ++++++++++++++++++++++++++++++++++++++++++++++ h=Help ++++ Select number [1-10]:
+++++++++++++++++++++++++++++++++++++++++++ Menu V1.2 ++++ + /4/3/ Signal Logging ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + 1 - start ECG + 2 - stop ECG + 3 - start RESP + 4 - stop RESP + 5 - start PULS + 6 - stop PULS + 7 - start EXT + 8 - stop EXT + 9 - start all signals + 10 - stop all signals + ++++++++++++++++++++++++++++++++++++++++++++++ h=Help ++++ Select number [1-10]: