R

如何對齊/同步兩個信號?

  • July 5, 2012

我正在做一些研究,但一直停留在分析階段(應該更多地關注我的統計講座)。

我收集了兩個同時的信號:體積和胸部擴張變化的綜合流速。我想比較信號並最終希望從胸部擴張信號中得出體積。但首先我必須對齊/同步我的數據。

由於記錄不是在同一時間開始的,而且胸部擴張被捕獲的時間更長,我需要在胸部擴張數據集中找到與我的體積數據相對應的數據,並衡量它們的對齊程度。如果兩個信號不是在完全相同的時間開始,或者在不同比例和不同分辨率的數據之間開始,我不太確定如何處理。

我附上了兩個信號的示例(https://docs.google.com/spreadsheet/ccc?key=0As4oZTKp4RZ3dFRKaktYWEhZLXlFbFVKNmllbGVXNHc),如果我可以提供任何進一步的信息,請告訴我。

該問題詢問當以規則但不同的間隔對序列進行採樣時,如何找到一個時間序列(“擴展”)滯後於另一個(“體積”)的量。

在這種情況下,兩個系列都表現出合理的連續行為,如圖所示。這意味著 (1) 可能需要很少或不需要初始平滑,並且 (2) 重新採樣可以像線性或二次插值一樣簡單。由於平滑度,二次方可能會稍微好一些。 重採樣後,通過最大化互相關找到滯後,如線程所示,對於兩個偏移採樣的數據序列,它們之間的偏移量的最佳估計是多少?.


為了說明,我們可以使用問題中提供的數據,R用於偽代碼。讓我們從基本功能、互相關和重採樣開始:

cor.cross <- function(x0, y0, i=0) {
 #
 # Sample autocorrelation at (integral) lag `i`:
 # Positive `i` compares future values of `x` to present values of `y`';
 # negative `i` compares past values of `x` to present values of `y`.
 #
 if (i < 0) {x<-y0; y<-x0; i<- -i}
 else {x<-x0; y<-y0}
 n <- length(x)
 cor(x[(i+1):n], y[1:(n-i)], use="complete.obs")
}

這是一個粗略的算法:基於 FFT 的計算會更快。但是對於這些數據(涉及大約 4000 個值)來說已經足夠了。

resample <- function(x,t) {
 #
 # Resample time series `x`, assumed to have unit time intervals, at time `t`.
 # Uses quadratic interpolation.
 #
 n <- length(x)
 if (n < 3) stop("First argument to resample is too short; need 3 elements.")
 i <- median(c(2, floor(t+1/2), n-1)) # Clamp `i` to the range 2..n-1
 u <- t-i
 x[i-1]*u*(u-1)/2 - x[i]*(u+1)*(u-1) + x[i+1]*u*(u+1)/2
}

我將數據下載為逗號分隔的 CSV 文件並去掉了它的標題。(標題對 R 造成了一些我不想診斷的問題。)

data <- read.table("f:/temp/a.csv", header=FALSE, sep=",", 
                   col.names=c("Sample","Time32Hz","Expansion","Time100Hz","Volume"))

注意 :此解決方案假定每個系列的數據都按時間順序排列,其中任何一個都沒有間隙。 這允許它使用值中的索引作為時間的代理,並通過時間採樣頻率縮放這些索引以將它們轉換為時間。

事實證明,這些儀器中的一種或兩種會隨著時間的推移而略有漂移。在繼續之前消除這些趨勢是很好的。此外,由於最後音量信號逐漸變細,我們應該將其剪掉。

n.clip <- 350      # Number of terminal volume values to eliminate
n <- length(data$Volume) - n.clip
indexes <- 1:n
v <- residuals(lm(data$Volume[indexes] ~ indexes))
expansion <- residuals(lm(data$Expansion[indexes] ~ indexes)

我重新採樣頻率較低的系列,以便從結果中獲得最精確的結果。

e.frequency <- 32  # Herz
v.frequency <- 100 # Herz
e <- sapply(1:length(v), function(t) resample(expansion, e.frequency*t/v.frequency))

現在可以計算互相關——為了提高效率,我們只搜索一個合理的滯後窗口——並且可以識別找到最大值的滯後。

lag.max <- 5       # Seconds
lag.min <- -2      # Seconds (use 0 if expansion must lag volume)
time.range <- (lag.min*v.frequency):(lag.max*v.frequency)
data.cor <- sapply(time.range, function(i) cor.cross(e, v, i))
i <- time.range[which.max(data.cor)]
print(paste("Expansion lags volume by", i / v.frequency, "seconds."))

輸出告訴我們擴展滯後了 1.85 秒。(如果最後 3.5 秒的數據沒有被剪裁,輸出將是 1.84 秒。)

以多種方式檢查所有內容是個好主意,最好是目視檢查。一、互相關函數

plot(time.range * (1/v.frequency), data.cor, type="l", lwd=2,
    xlab="Lag (seconds)", ylab="Correlation")
points(i * (1/v.frequency), max(data.cor), col="Red", cex=2.5)

互相關圖

接下來,讓我們及時註冊這兩個系列,並將它們一起繪製在相同的軸上

normalize <- function(x) {
 #
 # Normalize vector `x` to the range 0..1.
 #
 x.max <- max(x); x.min <- min(x); dx <- x.max - x.min
 if (dx==0) dx <- 1
 (x-x.min) / dx
}
times <- (1:(n-i))* (1/v.frequency)
plot(times, normalize(e)[(i+1):n], type="l", lwd=2, 
    xlab="Time of volume measurement, seconds", ylab="Normalized values (volume is red)")
lines(times, normalize(v)[1:(n-i)], col="Red", lwd=2)

註冊地塊

看起來還不錯! 不過,我們可以通過散點圖更好地了解配準質量。我按時間改變顏色以顯示進度。

colors <- hsv(1:(n-i)/(n-i+1), .8, .8)
plot(e[(i+1):n], v[1:(n-i)], col=colors, cex = 0.7,
    xlab="Expansion (lagged)", ylab="Volume")

散點圖

我們正在尋找沿著一條線來回追踪的點:從這條線的變化反映了膨脹對體積的時滯響應中的非線性。雖然有一些變化,但它們非常小。然而,這些變化如何隨時間變化可能具有一定的生理意義。統計學的美妙之處,尤其是它的探索性和視覺方面,是它如何傾向於創造好的問題想法以及有用的答案。

引用自:https://stats.stackexchange.com/questions/31666

comments powered by Disqus