In this very synthetic tutorial, we will walk readers through different analyses and example of usages of the latest version of R package crqa() as they appear in Coco, et, al., (in press). Our goal is to provide readers with a reference guide to all analyses that are possible with crqa(). We refer readers to such a paper for greater details about the theoretical insights associated with these sets of analysis.
library(crqa) # The crqa() package
library(pracma) # To simulate data (sine waves)
data(crqa) # Load the data available in the package
options(scipen = 999) # Disable scientific notation
# Alpha colours for illustrating diagonal|windowed-crqa
= "#FF000080" # gray 80
diagcol = "#36648B80" # gray 51
windcol
## The focus window for the text example (Figure 4)
= c(100, 0, 1800, 2000)
xd = c(0, 100, 2000, 2000)
yd
= c(0, 0, 100, 100)
xw = c(0, 100, 100, 0) yw
= list(unit = 200, labelx = "", labely = "",
parC cols = "black", pcex = .3, pch = 20, las = 0,
labax = seq(0, nrow(Figure_1), 200), labay = seq(0, nrow(Figure_1), 200))
par(mfrow = c(1, 3), font.lab = 2, font.axis = 2, cex.lab = 2, cex.axis = 1.5)
plot(Figure_1$sinus, type = "l", xlab = "", ylab = "", axes = F, lwd = 2)
box()
plot(Figure_1$lorenz, type = "l", xlab = "", ylab = "", axes = F, lwd = 2)
box()
plot(Figure_1$wnoise, type = "l", xlab = "", ylab = "", axes = F, lwd = 2)
box()
<- crqa(ts1 = Figure_1$sinus, ts2 = Figure_1$sinus, delay = 1,
SINrqa1 embed = 1, rescale = 0, radius = 0.03, normalize = 0,
side = 'both', method = 'rqa', datatype = 'continuous')
<- crqa(ts1 = Figure_1$lorenz, ts2 = Figure_1$lorenz, delay = 1,
LORrqa1 embed = 1, rescale = 0, radius = 0.03, normalize = 0,
side = 'both', method = 'rqa', datatype = 'continuous')
<- crqa(ts1 = Figure_1$wnoise, ts2 = Figure_1$wnoise, delay = 1,
WNOISErqa1 embed = 1, rescale = 0, radius = 0.003, normalize = 0,
side = 'both', method = 'rqa', datatype = 'continuous')
par(mfrow = c(1,3), font.lab = 2, font.axis = 2, cex.lab = 2, cex.axis = 1.5,
mar = c(1, 5.5, 3, 2), oma = c(1,1,2,1))
plotRP(SINrqa1$RP, parC)
plotRP(LORrqa1$RP, parC)
plotRP(WNOISErqa1$RP, parC)
<- crqa(ts1 = Figure_1$sinus, ts2 = Figure_1$sinus, delay = 110,
SINrqa2 embed = 2, rescale = 0, radius = 0.02, normalize = 0,
side = 'both', method = 'rqa', datatype = 'continuous')
<- crqa(ts1 = Figure_1$lorenz, ts2 = Figure_1$lorenz, delay = 10,
LORrqa2 embed = 3, rescale = 0, radius = 1.3, normalize = 0,
side = 'both', method = 'rqa', datatype = 'continuous')
<- crqa(ts1 = Figure_1$wnoise, ts2 = Figure_1$wnoise, delay = 1,
WNOISErqa2 embed = 3, rescale = 0, radius = 0.1, normalize = 0,
side = 'both', method = 'rqa', datatype = 'continuous')
par(mfrow = c(1,3), font.lab = 2, font.axis = 2, cex.lab = 2, cex.axis = 1.5,
mar = c(1, 5.5, 3, 2), oma = c(1,1,2,1))
## The sinusoid has a longer delay, so we need to change the label to reflect this
$labax = seq(0, 1000, 200); parC$labay = seq(0,1000, 200)
parCplotRP(SINrqa2$RP, parC)
$labax = seq(0, 1200, 200); parC$labay = seq(0,1200, 200)
parCplotRP(LORrqa2$RP, parC)
plotRP(WNOISErqa2$RP, parC)
= as.numeric(as.matrix(Figure_2)) # Make it a vector Figure_2
par(font.lab = 2, font.axis = 2, cex.lab = 1.7, cex.axis = 1.5)
plot(Figure_2[1:42], Figure_2[4:45], type = 'b',
las = 1, xlab = 'dimension 1', ylab = 'dimension 2',
main = '', lwd = 2)
points(Figure_2[1], Figure_2[4], pch = 19, cex = 1.2, col = "blue")
points(Figure_2[6], Figure_2[9], pch = 19, cex = 1.2, col = "green")
points(Figure_2[9], Figure_2[12], pch = 19, cex = 1.2, col = "red")
symbols(x = Figure_2[9], y = Figure_2[12], circles = 0.25, add = TRUE,
inches = FALSE)
points(Figure_2[24], Figure_2[27], pch = 19, cex = 1.2, col = "red")
points(Figure_2[38], Figure_2[41], pch = 19, cex = 1.2, col = "red")
points(Figure_2[39], Figure_2[42], pch = 19, cex = 1.2, col = "red")
text(x = -0.5, y = -1.1, labels = "Threshold", adj = 1)
text(x = -0.6, y = -0.2, adj = 0,
label = "Recurrences of the point")
text(x = -0.6, y = -0.3, adj = 0,
bquote('('~X[9]*';'~X[9+tau]*')'))
par(font.lab = 2, font.axis = 2, cex.lab = 2, cex.axis = 1.5)
plot(Figure_2, 45:1, type = 'b', las = 1, xlab = "", ylab = "time",
yaxt = "n")
points(Figure_2[1], 45, pch = 19, cex = 1.2, col = "blue")
points(Figure_2[6], 40, pch = 19, cex = 1.2, col = "green")
points(Figure_2[9], 37, pch = 19, cex = 1.2, col = "red")
axis(side = 2, at = seq(from = 45, to = 5, by = -10), las = 1,
labels = c(0, 10, 20, 30, 40), tick = T)
par(font.lab = 2, font.axis = 2, cex.lab = 2, cex.axis = 1.5)
plot(Figure_2[4:45], type = 'b', las = 1, xlab = 'time', ylab = '')
points(1, Figure_2[4], pch = 19, cex = 1.2, col = "blue")
points(6, Figure_2[9], pch = 19, cex = 1.2, col = "green")
points(9, Figure_2[12], pch = 19, cex = 1.2, col = "red")
<- crqa(ts1 = Figure_2, ts2 = Figure_2, delay = 3, embed = 2,
fig2rqa radius = 0.25, method = 'rqa', datatype = 'continuous')
$unit = 10; parC$labax = ""; parC$labay = ""; parC$pcex = 1; parC$pch = 15
parC
par(font.lab = 2, font.axis = 2, cex.lab = 2, cex.axis = 1.5)
plotRP(fig2rqa$RP, parC)
= which(fig2rqa$RP[9,] == T)
ixi_9 points(rep(9, length(ixi_9)), ixi_9, col = "red", pch = 15, cex = 1)
points(ixi_9, rep(9, length(ixi_9)), col = "red", pch = 15, cex = 1)
par(mfrow = c(1,2), font.lab = 2, font.axis = 2, cex.lab = 2, cex.axis = 1.5,
mar = c(4.5, 4.5, 1, 1))
<- Figure_3[,1]
L1 <- Figure_3[,2]
L2
# Panel A.
plot(L2, type = "l", xlab = "time", ylab = "", lwd = 2)
lines(L1, col = "red", lwd = 2)
# Panel B
# Run DCRP analysis on data
<- drpfromts(ts1 = L2, ts2 = L1, delay = 1, embed = 1,
Fig3 windowsize = 20, radius = 0.02, datatype = "continuous",
rescale = 0, normalize = 0, mindiagline = 2,
minvertline = 2, tw = 0, side = 'both', method = "crqa")
# Plot the recurrence profile
plot(-20:20, Fig3$profile, type = "b",
lwd = 2, ylab = "Recurrence Rate", xlab = "Lag", cex = 0.8)
abline(v = 0, lty = 2)
## Setting the parameters
= 1; embed = 1; rescale = 0; radius = 0.0001;
delay = 0; mindiagline = 2; minvertline = 2;
normalize = 1; whiteline = FALSE; recpt = FALSE;
tw = "both"; method = 'rqa'; metric = 'euclidean';
side = "categorical"
datatype
## Run the analysis
= crqa(text, text, delay, embed, rescale, radius, normalize,
ans
mindiagline, minvertline, tw, whiteline, recpt, side, method, metric,
datatype)#> Warning in crqa(text, text, delay, embed, rescale, radius, normalize,
#> mindiagline, : Your input data was provided either as character or factor, and
#> recoded as numerical identifiers
## Update plotting arguments
= list(unit = 10, labelx = "Time", labely = "Time",
parC cols = "black", pcex = .5, pch = 15, las = 0,
labax = seq(0, nrow(ans$RP), 10), labay = seq(0, nrow(ans$RP), 10))
## Generate the plot
par(font.lab = 2, font.axis = 2, cex.lab = 2, cex.axis = 1.5)
plotRP(ans$RP, parC)
rect(81, 81, 110, 110, border = "red", lwd = 2)
= text[81:110]
text_zoom
= crqa(text_zoom, text_zoom, delay, embed, rescale, radius, normalize,
ans_zoom
mindiagline, minvertline, tw, whiteline, recpt, side, method, metric,
datatype)#> Warning in crqa(text_zoom, text_zoom, delay, embed, rescale, radius,
#> normalize, : Your input data was provided either as character or factor, and
#> recoded as numerical identifiers
# Add to the graphics parameters the labels for the axes (x,y)
$labay = parC$labax = text_zoom
parC
# Change the las argument to print the words vertically
$las = 2 # make it vertical
parC
# Change the unit to make it word by word
$unit = 1 # make it vertical
parC
# Change the label of x, y axis
$labelx = parC$labely = "Words"
parC
par(font.lab = 2, font.axis = 2, cex.lab = 2, cex.axis = 1.5)
plotRP(ans_zoom$RP, parC)
= eyemovement$listener
listener = eyemovement$narrator
narrator
= 1; embed = 1; rescale = 0; radius = .01;
delay = 0; mindiagline = 2; minvertline = 2;
normalize = 0; whiteline = FALSE; recpt = FALSE; side = "both"
tw = 'crqa'; metric = 'euclidean';
method = "categorical"
datatype
## Compute cross-recurrence quantification analysis
= crqa(narrator, listener, delay, embed, rescale, radius, normalize,
ans
mindiagline, minvertline, tw, whiteline, recpt, side, method, metric,
datatype)
## Uncomment to check performance (but need to load profvis)
# pf = profvis(crqa(narrator, listener, delay, embed, rescale, radius, normalize,
# mindiagline, minvertline, tw, whiteline, recpt, side, method, metric,
# datatype))
= as.matrix(ans$RP)
RP = unlist(ans[1:10])
results
## Change again the plotting parameters
$labelx = parC$labely = "Time (sec.)"
parC$unit = 333 ## in ms
parC$pcex = .1 # make this much smaller as we have loads of points
parC$labax = parC$labay = seq(0, 60, 10)
parC$las = 1
parC= 50 windowstep
par(font.lab = 2, font.axis = 2, cex.lab = 2, cex.axis = 1.5)
plotRP(RP, parC)
polygon(xd, yd, col = diagcol, border = F) # the diagonal
polygon(xw, yw, col = windcol, border = F) # the first window
for (w in 1:10){ # the number of overlapping windows that we want to plot
polygon(xw + windowstep, yw + windowstep, col = windcol, border = F) # # the second window
polygon(xw + w*windowstep, yw + w*windowstep, col = windcol, border = F) # the third window
polygon(xw + w*windowstep, yw + w*windowstep, col = windcol, border = F) # the fourth window
}
## Construct the time-course for the diagonal profile
= round( seq(-3300,3300,33)/1000, digit = 2)
timecourse
## Show diagonal-profile CRQA with eye-movement data
= drpfromts(narrator, listener, windowsize = 100,
res radius = 0.001, delay = 1, embed = 1, rescale = 0,
normalize = 0, mindiagline = 2, minvertline = 2,
tw = 0, whiteline = F, recpt = F, side = 'both',
method = 'crqa', metric = 'euclidean',
datatype = 'continuous')
= res$profile*100
profile
par(font.lab = 2, font.axis = 2, cex.lab = 1.8, cex.axis = 1.3,
mar = c(4.5, 5.5, 1, 2))
plot(timecourse, profile, type = "l", lwd = 2.5, xlab = "Lag (seconds)",
ylab = "Recurrence Rate %")
= 1; embed = 1; rescale = 1; radius = 0.001;
delay = 0; mindiagline = 2; minvertline = 2;
normalize = 0; whiteline = FALSE; recpt = FALSE; side = "both"
tw = 'crqa'; metric = 'euclidean';
method = "categorical"; windowsize = 100;
datatype = 50; windowstep = 20
lagwidth
## Calculate windowed cross-recurrence
= windowdrp(narrator, listener, windowstep, windowsize, lagwidth,
res radius = 0.001, delay = 1, embed = 1, rescale = 0,
normalize = 0, mindiagline = 2, minvertline = 2,
tw = 0, whiteline = F, side = 'both',
method = 'crqa', metric = 'euclidean',
datatype = "continuous")
= res$profile*100
profile
= round( seq(1, length(profile), 1)*windowstep*.033, digit = 1)
timecourse
par(font.lab = 2, font.axis = 2, cex.lab = 1.8, cex.axis = 1.3,
mar = c(4.5, 5.5, 1, 2))
plot(timecourse, profile, type = "l", lwd = 2.5,
xlab = "Time (seconds)", ylab = "Recurrence Rate %")
= eyemovement$listener
listener = eyemovement$narrator
narrator
= 1; embed = 1; rescale = 0; radius = 0.001;
delay = 0; mindiagline = 2; minvertline = 2;
normalize = 0; whiteline = FALSE; recpt = FALSE; side = "both"
tw = 'crqa'; metric = 'euclidean';
method = "continuous";
datatype = 100; windowstep = 20
windowsize = FALSE
trend
= wincrqa(listener, narrator, windowstep, windowsize, delay, embed,
ans
radius, rescale, normalize, mindiagline, minvertline,
tw, whiteline, recpt, side, method, metric,
datatype, trend)
= as.numeric(ans$RR)
profile
plot(profile, type = 'l')
# Reduce the dimensionality of the time series to reduce runtime
# handset = handmovement[1:3000, ]
= handmovement[1:1000, ]
handset
= cbind(handset$P1_TT_d, handset$P1_TT_n)
P1 = cbind(handset$P2_TT_d, handset$P2_TT_n)
P2
= 5; embed = 2; rescale = 0; radius = .1;
delay = 0; mindiagline = 10; minvertline = 10;
normalize = 0; whiteline = FALSE; recpt = FALSE; side = "both"
tw = 'mdcrqa'; metric = 'euclidean';
method = "continuous"
datatype
= crqa(P1, P2, delay, embed, rescale, radius, normalize,
ans
mindiagline, minvertline, tw, whiteline, recpt, side, method, metric,
datatype)
= ans$RP
RP = unlist(ans[1:10])
results print(results)
#> RR DET NRLINE maxL L ENTR
#> 19.6643519 75.4671721 4024.0000000 161.0000000 36.5111829 3.7221108
#> rENTR LAM TT catH
#> 0.7408836 83.9759197 23.3335028 NA
## Adjust the plotting parameters
$unit = 300
parC$pcex = .1 # make this much smaller as we have loads of points
parC$labax = parC$labay = seq(0, nrow(RP), parC$unit)
parC
plotRP(RP, parC)
## Estimate parameters for uni-dimensional RQA using simulated data generated off sinusoids.
= seq(0.1, 200, .1)
ts1 = sin(ts1) + linspace(0, 1,length(ts1));
ts1 = ts1
ts2
= list(method = "rqa", metric = "euclidean", maxlag = 20,
par radiusspan = 100, radiussample = 40, normalize = 0,
rescale = 4, mindiagline = 10, minvertline = 10, tw = 0,
whiteline = FALSE, recpt = FALSE, side = "both",
datatype = "continuous", fnnpercent = 10, typeami = 'mindip')
= optimizeParam(ts1, ts2, par, min.rec = 2, max.rec = 5) # it may take some time
results print(unlist(results))
#> radius emddim delay
#> 0.1755553 2.0000000 18.0000000
= crqa(ts1, ts2, delay = results$delay, embed = results$emddim,
ans radius = results$radius)
rescale,
unlist(print(ans[1:10]))
#> $RR
#> [1] 2.028753
#>
#> $DET
#> [1] 99.39771
#>
#> $NRLINE
#> [1] 7127
#>
#> $maxL
#> [1] 1982
#>
#> $L
#> [1] 11.11492
#>
#> $ENTR
#> [1] 2.666816
#>
#> $rENTR
#> [1] 0.7181268
#>
#> $LAM
#> [1] 97.9861
#>
#> $TT
#> [1] 3.205311
#>
#> $catH
#> [1] NA
#> RR DET NRLINE maxL L ENTR
#> 2.0287532 99.3977113 7127.0000000 1982.0000000 11.1149151 2.6668157
#> rENTR LAM TT catH
#> 0.7181268 97.9860972 3.2053113 NA
Let optimize parameters of multi-dimensional data using the hand-movements.
## Change a few parameters to set this
$method = "mdcrqa";par$fnnpercent = NA; par$typeami = NA;
par$nbins = 50; par$criterion = "firstBelow"; par$threshold = 1.6;
par$maxEmb = 20; par$numSamples = 500; par$Rtol = 10; par$Atol = 2
par
= optimizeParam(P1, P2, par, min.rec = 2, max.rec = 5) # it may take some time
results #> Warning in sqrt((temp[yRd1[j]] - r2d[j])/r2d[j]): NaNs produced
#> Warning in sqrt((temp[yRd1[j]] - r2d[j])/r2d[j]): NaNs produced
#> Warning in sqrt((temp[yRd1[j]] - r2d[j])/r2d[j]): NaNs produced
#> Warning in sqrt((temp[yRd1[j]] - r2d[j])/r2d[j]): NaNs produced
#> Warning in sqrt((temp[yRd1[j]] - r2d[j])/r2d[j]): NaNs produced
#> Warning in sqrt((temp[yRd1[j]] - r2d[j])/r2d[j]): NaNs produced
#> Warning in sqrt((temp[yRd1[j]] - r2d[j])/r2d[j]): NaNs produced
#> Warning in sqrt((temp[yRd1[j]] - r2d[j])/r2d[j]): NaNs produced
#> Warning in sqrt((temp[yRd1[j]] - r2d[j])/r2d[j]): NaNs produced
#> Warning in sqrt((temp[yRd1[j]] - r2d[j])/r2d[j]): NaNs produced
#> Warning in sqrt((temp[yRd1[j]] - r2d[j])/r2d[j]): NaNs produced
#> Warning in sqrt((temp[yRd1[j]] - r2d[j])/r2d[j]): NaNs produced
#> Warning in sqrt((temp[yRd1[j]] - r2d[j])/r2d[j]): NaNs produced
print(unlist(results))
#> radius emddim delay
#> 0.04152206 4.00000000 2.00000000
= crqa(P1, P2, delay = results$delay, embed = results$emddim,
ans radius = results$radius, normalize,
rescale,
mindiagline, minvertline, tw, whiteline, recpt, side, method, metric,
datatype)
print(ans[1:10])
#> $RR
#> [1] 9.457348
#>
#> $DET
#> [1] 80.5687
#>
#> $NRLINE
#> [1] 3136
#>
#> $maxL
#> [1] 87
#>
#> $L
#> [1] 24.0067
#>
#> $ENTR
#> [1] 3.417769
#>
#> $rENTR
#> [1] 0.7965975
#>
#> $LAM
#> [1] 91.88695
#>
#> $TT
#> [1] 31.73394
#>
#> $catH
#> [1] NA
= 10; maxlag = 10; criterion = "firstBelow"; threshold = exp(-1)
nbins
data(crqa) ## load the data
= handmovement[1:300, ] ## take less points
handset
mdDelay(handset, nbins, maxlag, criterion, threshold)
#> [1] 2
= 1; maxEmb = 10; numSamples = 500; Rtol = 10; Atol = 2
tau
mdFnn(handset, tau, maxEmb, numSamples, Rtol, Atol)
#> $fnnPerc
#> [1] 100.000000 4.123711 2.749141 2.405498 3.780069 4.467354
#> [7] 4.810997 4.123711 4.810997 4.467354
#>
#> $embTimes
#> [1] 1 2 3 4 5 6 7 8 9 10
= range(Figure_6$speed)
YLIM = range(Figure_6$memory)
YLIM2
= subset(Figure_6, Figure_6$typeRQA == "full")
perfFull = subset(Figure_6, Figure_6$typeRQA == "piece")
perfPiece
= unique(perfPiece$blocksize)
sizes
## Assign PCH to blocksize so that I can plot it
$pch = apply(data.frame(perfPiece$blocksize),1,function(x) which(x == sizes))
perfPiece
= rainbow(length(sizes))
colors ## Assign the color palette to the block size
$colors = apply(data.frame(perfPiece$blocksize), 1, function(x){
perfPiece= which(x == sizes)
ixi = colors[ixi]}) x
plot(perfPiece$datapoint, perfPiece$speed, type = "p", col = perfPiece$colors,
cex = 2.1, xlab = "Number of Data Points", pch = perfPiece$pch,
ylab = "Time (sec)", ylim = YLIM, main = "Speed")
points(perfFull$datapoint, perfFull$speed, type = "p", col = "black",
pch = 19, cex = 2.1)
plot(perfPiece$datapoint, perfPiece$memory, type = "p", col = perfPiece$colors,
cex = 2.1, xlab = "Number of Data Points", pch = perfPiece$pch,
ylab = "Max Memory (Mb)", ylim = YLIM2, main = "Memory")
points(perfFull$datapoint, perfFull$memory, type = "p", col = "black",
pch = 19, cex = 2.1)
legend("topleft",legend = c(unique(perfPiece$blocksize), "full"),
col = c(unique(perfPiece$colors), "black"), cex = 1.5,
pch = c(unique(perfPiece$pch), 19), bty = "n")
Coco, Monster, Leonardi, Dale & Wallot (in press). Unidimensional and Multidimensional Methods for Recurrence Quantification Analysis with crqa(). The R Journal.