knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
library(ARCOS) library(data.table) library(ggplot2) library(ggthemes) library(testthat) ## Custom functions # Wrapper function for testing myTest = function(inDTcalc, inFtrue, inDir = "testdata") { resTest = testthat::test_that("test chunk", { locDTtrueRes = fread(file.path(system.file(inDir, package="ARCOS"), inFtrue)) attr(inDTcalc, "sorted") = NULL attr(inDTcalc, "class") = c("data.table", "data.frame") if ("clTrackID" %in% names(locDTtrueRes)) setnames(inDTcalc, "collid", "clTrackID") expect_equal(inDTcalc, locDTtrueRes) }) }
Demonstration of the ARCOS algorithm on synthetic data used for unit testing.
Only spatial clusters in consecutive frames are linked.
A single object that is active at frames 2, [4,5], and [7,9]. There are gaps of inactivity at frames 3 and 6.
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "1central_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts, size = 3)
The parameter nPrev = 1L
tells the tracking algorithm to link events only from consecutive frames, i.e. it looks back only 1 frame. Hence, clustering will yield 3 events at frames 2, [4,5], [7,8,9].
dcoll = ARCOS::trackColl(obj = dts[m>0], eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(time, trackID, collid)], "1central_res.csv")
Consider 7 objects that become subsequently active every 2 frames. It mimics an activity wave spreading from object #4 to neighbouring objects.
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "3spreading_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts[m>0], size = 3)
By linking events that are 1 frame apart (parameter nPrev = 1L
), the tracking algorithm identifies 3 collective events.
dcoll = ARCOS::trackColl(obj = dts[m>0], eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(time, trackID, collid)], "3spreading_res.csv")
Consider two objects 2 spatial units apart that beocme active at overlapping time points.
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "5overlapping_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts[m>0], size = 3)
dcoll = ARCOS::trackColl(obj = dts[m>0], eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(time, trackID, collid)], "5overlapping_res.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "6overlapping_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts[m>0], size = 3)
dcoll = ARCOS::trackColl(obj = dts[m>0], eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(time, trackID, collid)], "6overlapping_res.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "1centralGrowing_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts[m>0], size = 3)
dcoll = ARCOS::trackColl(obj = dts[m>0], eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(time, trackID, collid)], "1centralGrowing_res.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "2centralGrowing_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts[m>0], size = 3)
dcoll = ARCOS::trackColl(obj = dts[m>0], eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(time, trackID, collid)], "2centralGrowing_res.csv")
This test addresses a problem of two different activation events (objects #1 and 2) that spread to a common, equidistant neighbour (object #3).
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "2with1commonSym_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts[m>0], size = 3)
Since there's no obvious way to treat this symmetric case, the algorithm assumes that the common neighbour becomes active due to one of the initiators. Here, the activation wave #2 from object #2 spreads to object #3, while the activation wave #1 from object #1 is confined only to that object.
dcoll = ARCOS::trackColl(obj = dts[m>0], eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(time, trackID, collid)], "2with1commonSym_res.csv")
A similar situation to the previous case but object #3 is no longer equidistant to objects #1 and 2. Instead, it is closer to object #1.
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "2with1commonAsym_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts[m>0], size = 3)
Since the neighbourhood cut-off is 1 distance unit (parameter eps
), the collective activation #1 from object #1 spreads to object #3.
dcoll = ARCOS::trackColl(obj = dts[m>0], eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(time, trackID, collid)], "2with1commonAsym_res.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "multipleSimulNewObjects_in.csv"), colPos = "pos", colFrame = "t", colIDobj = "id") ARCOS::plotTracks(dts, size = 3)
dcoll = ARCOS::trackColl(obj = dts, eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(t, id, collid)], "multipleSimulNewObjects_out.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "multipleSubseq4NewObjectsAfter1_in.csv"), colPos = "pos", colFrame = "t", colIDobj = "id") ARCOS::plotTracks(dts, size = 3)
dcoll = ARCOS::trackColl(obj = dts, eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(t, id, collid)], "multipleSubseq4NewObjectsAfter1_out.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "multipleSubseq3NewObjectsAfter2_in.csv"), colPos = "pos", colFrame = "t", colIDobj = "id") ARCOS::plotTracks(dts, size = 3)
dcoll = ARCOS::trackColl(obj = dts, eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(t, id, collid)], "multipleSubseq3NewObjectsAfter2_out.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "multipleSubseq4NewObjectsAfter2_in.csv"), colPos = "pos", colFrame = "t", colIDobj = "id") ARCOS::plotTracks(dts, size = 3)
dcoll = ARCOS::trackColl(obj = dts, eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(t, id, collid)], "multipleSubseq4NewObjectsAfter2_out.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "multipleSubseqNewObjects_in.csv"), colPos = "pos", colFrame = "t", colIDobj = "id") ARCOS::plotTracks(dts, size = 3)
dcoll = ARCOS::trackColl(obj = dts, eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(t, id, collid)], "multipleSubseqNewObjects_out.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "1objSplit_in.csv"), colPos = "pos", colFrame = "t", colIDobj = "id") ARCOS::plotTracks(dts, size = 3)
dcoll = ARCOS::trackColl(obj = dts, eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(t, id, collid)], "1objSplit_res.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "2objSplit_in.csv"), colPos = "pos", colFrame = "t", colIDobj = "id") ARCOS::plotTracks(dts, size = 3)
dcoll = ARCOS::trackColl(obj = dts, eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(t, id, collid)], "2objSplit_res.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "2objCross_in.csv"), colPos = "pos", colFrame = "t", colIDobj = "id") ARCOS::plotTracks(dts, size = 3)
dcoll = ARCOS::trackColl(obj = dts, eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(t, id, collid)], "2objCross_res.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "2objCrossCommon_in.csv"), colPos = "pos", colFrame = "t", colIDobj = "id") ARCOS::plotTracks(dts, size = 3)
dcoll = ARCOS::trackColl(obj = dts, eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(t, id, collid)], "2objCrossCommon_res.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "2objMergeSplitCommon_in.csv"), colPos = "pos", colFrame = "t", colIDobj = "id") ARCOS::plotTracks(dts, size = 3)
dcoll = ARCOS::trackColl(obj = dts, eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(t, id, collid)], "2objMergeSplitCommon_res.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "2objMergeSplitCross_in.csv"), colPos = "pos", colFrame = "t", colIDobj = "id") ARCOS::plotTracks(dts, size = 3)
dcoll = ARCOS::trackColl(obj = dts, eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(t, id, collid)], "2objMergeSplitCross_res.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "2objMergeSplitNear_in.csv"), colPos = "pos", colFrame = "t", colIDobj = "id") ARCOS::plotTracks(dts, size = 3)
dcoll = ARCOS::trackColl(obj = dts, eps = 1.0, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(t, id, collid)], "2objMergeSplitNear_res.csv")
This test illustrates an important feature of the algorithm. At time 5, object #2 is within the eps radius 1.5 of object #1. This triggers the inheritance of cluster IDs of the nearest neighbours from time 4. However, the nearest neighbour of object #3 is object #4 (1.9 distance vs. 2 to object #1). Consequently, collective IDs of the new cluster are "split" between ID #1 and #2.
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "2clusters1delayed_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts, size = 3) + scale_x_continuous(breaks = 1:7) + theme(panel.grid.minor = element_blank())
dcoll = ARCOS::trackColl(obj = dts, eps = 1.5, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3) + scale_x_continuous(breaks = 1:7) + theme(panel.grid.minor = element_blank())
myTest(dcoll[, .(time, trackID, collid)], "2clusters1delayed_out.csv")
This test illustrates another important feature of the algorithm.
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "2clustersMerging_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts, size = 3) + scale_x_continuous(breaks = 1:10) + theme(panel.grid.minor = element_blank())
dcoll = ARCOS::trackColl(obj = dts, eps = 1.5, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3) + scale_x_continuous(breaks = 1:10) + theme(panel.grid.minor = element_blank())
myTest(dcoll[, .(time, trackID, collid)], "2clustersMerging_out.csv")
This test illustrates another important feature of the algorithm.
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "2clustersCrossing_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts, size = 3) + scale_x_continuous(breaks = 1:10) + theme(panel.grid.minor = element_blank())
dcoll = ARCOS::trackColl(obj = dts, eps = 1.5, minClSz = 1L, nPrev = 1L, deb = F) ARCOS::plotTracks(dcoll, size = 3) + scale_x_continuous(breaks = 1:10) + theme(panel.grid.minor = element_blank())
myTest(dcoll[, .(time, trackID, collid)], "2clustersCrossing_out.csv")
Spatial clusters are linked 2 frames back, thus a one-frame-gap is allowed in a collective event.
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "1central_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts, size = 3)
Here parameter nPrev = 2L
, which links events from two consecutive frames, i.e. it looks back 2 frames. Hence, clustering will yield 1 continuous events.
dcoll = ARCOS::trackColl(obj = dts[m>0], eps = 1.0, minClSz = 1L, nPrev = 2L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(time, trackID, collid)], "1central2prev_res.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "3spreading_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts[m>0], size = 3)
dcoll = ARCOS::trackColl(obj = dts[m>0], eps = 1.0, minClSz = 1L, nPrev = 2L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(time, trackID, collid)], "3spreading2prev_res.csv")
dts = ARCOS::loadDataFromFile(file.path(system.file("testdata", package="ARCOS"), "5overlapping_in.csv"), colPos = "x", colMeas = "m", colFrame = "time", colIDobj = "trackID") ARCOS::plotTracks(dts[m>0], size = 3)
dcoll = ARCOS::trackColl(obj = dts[m>0], eps = 1.0, minClSz = 1L, nPrev = 2L, deb = F) ARCOS::plotTracks(dcoll, size = 3)
myTest(dcoll[, .(time, trackID, collid)], "5overlapping2prev_res.csv")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.