Philips MRI scanners record
cardiac, respiratory, and motion signals alongside the BOLD acquisition
via the Physiological Monitoring Unit (PMU). mrpheus can read these
.log files, detect QRS complexes with the Pan-Tompkins
algorithm, and compute instantaneous heart rate — producing cardiac
regressors ready for RETROICOR or HRV analysis.
read_philips_physlog() parses any Philips PMU
.log file and returns a mrpheus_physlog object
containing the signal matrix, event markers, and recording metadata.
path <- system.file("extdata", "example_physlog.log", package = "mrpheus")
rec <- read_philips_physlog(path)
rec
#>
#> ── mrpheus Philips PMU recording ───────────────────────────────────────────────
#> ℹ Path: '/tmp/RtmpL20rL5/Rinstbb53b899e49/mrpheus/extdata/example_physlog.log'
#> ℹ System: wBTU (496 Hz)
#> ℹ Channels: v1raw, v2raw, v1, v2, ppu, resp, gx, gy, gz, mark
#> ℹ Samples: 9920 (0.3 min)
#> ℹ Markers: 52 eventsThe system argument sets the hardware preset:
# Wireless VCG (Achieva/Ingenia dStream) — default
rec <- read_philips_physlog(path, system = "wBTU")
# Older wired ECG system (500 Hz)
rec <- read_philips_physlog(path, system = "wired")
# Site-specific sampling rate
rec <- read_philips_physlog(path, system = "custom", sfreq = 400)The resolved sampling frequency is always at
rec$HDR$sfreq so nothing downstream needs to hardcode
it.
ecg <- as.double(rec$C[, "v1raw"])
ppu <- as.double(rec$C[, "ppu"])
resp <- as.double(rec$C[, "resp"])The wBTU layout provides ten channels:
| Channel | Contents |
|---|---|
v1raw, v2raw |
Raw VCG electrode voltages |
v1, v2 |
Processed VCG signals |
ppu |
Peripheral pulse unit (PPG, foot) |
resp |
Respiratory belt |
gx, gy, gz |
3-axis accelerometer |
mark |
Bit-encoded event marker |
detect_qrs() implements the Pan-Tompkins (1985)
algorithm and returns a mrpheus_qrs object.
qrs <- detect_qrs(ecg, fs = rec$HDR$sfreq)
qrs
#>
#> ── mrpheus QRS detection ───────────────────────────────────────────────────────
#> ℹ R-peaks detected: 50
#> ℹ Mean HR: 150 bpm
#> ℹ Filter delay: 37 samples (0.075 s)
#> ℹ Sampling rate: 496 HzR-peak indices are in qrs$qrs_i. Account for
qrs$delay if you need indices aligned to the raw
(pre-filter) ECG.
compute_hr_signal() converts R-peak indices into a
sample-by-sample instantaneous HR trace (bpm). It reads fs
from the mrpheus_qrs object directly:
To extract the physiology aligned to the fMRI scan, use the scanner-stop marker. This is more reliable than the start marker because the exact recording onset varies but the stop is always clean:
sfreq <- rec$HDR$sfreq
enddelay <- 42L
tr <- 0.392
vols <- 47L
stopidx <- tail(rec$I$ScannerStop, 1L) - enddelay
startidx <- max(1L, stopidx - round(vols * tr * sfreq))
epoch <- rec$C[startidx:stopidx, ]
cat("Epoch:", nrow(epoch), "samples /", round(nrow(epoch) / sfreq, 1), "s\n")
#> Epoch: 9139 samples / 18.4 sqrs_epoch <- detect_qrs(as.double(epoch[, "v1raw"]), fs = sfreq)
rr_t <- qrs_epoch$qrs_i[-1] / sfreq
rr_s <- diff(qrs_epoch$qrs_i) / sfreq
tr_times <- seq(0, vols * tr, by = tr)
rr_tr <- approx(rr_t, rr_s, xout = tr_times, method = "constant")$y
cat("RR per TR (first 5):", round(rr_tr[1:5] * 1000), "ms\n")
#> RR per TR (first 5): NA NA 399 399 399 msrr_tr is a length-vols vector ready for
RETROICOR phase computation or inclusion as a nuisance regressor in a
GLM.
library(mrpheus)
rec <- read_philips_physlog("sub-01_ses-01_physlog.log")
sfreq <- rec$HDR$sfreq
stopidx <- tail(rec$I$ScannerStop, 1L) - 42L
startidx <- stopidx - round(2300L * 0.392 * sfreq)
epoch <- rec$C[startidx:stopidx, ]
qrs <- detect_qrs(as.double(epoch[, "v1raw"]), fs = sfreq)
hr <- compute_hr_signal(qrs)
rr_tr <- approx(
x = qrs$qrs_i[-1] / sfreq,
y = diff(qrs$qrs_i) / sfreq,
xout = seq(0, 2300 * 0.392, by = 0.392),
method = "constant"
)$yPan J, Tompkins WJ. A real-time QRS detection algorithm. IEEE Trans Biomed Eng. 1985;32(3):230–236. https://doi.org/10.1109/TBME.1985.325532
Groot PFC. ReadPhilipsScanPhysLog (MATLAB). AMC Amsterdam. 2010.
Glover GH, Li TQ, Ress D. Image-based method for retrospective correction of physiological motion effects in fMRI: RETROICOR. Magn Reson Med. 2000;44(1):162–167.