Determine active or inactive states according to density based clustering method.
Source:R/activity2.R
activity2.Rd
Given an object of class "tracklets" containing a list of tracklets which contain two variable of interest the function use density based clustering as introduced in Ester et al. (1996). As a result, the function use the DBSCAN method from Hennig (2020) to discriminate active and inactive states in a 2d space by returning numeric values indicating whether the particle is "active" (1) or "inactive" (0).
Usage
activity2(
trackDat,
var1 = NULL,
var2 = NULL,
var1T = NULL,
var2T = NULL,
nbins = NULL,
eps = NULL,
minPts = NULL,
scale = TRUE,
na.rm = TRUE
)
Arguments
- trackDat
An object of class "tracklets" containing a list of tracklets and their characteristics classically used for further computations.
- var1
A character string indicating the name of the variable to use as the first dimension.
- var2
A character string indicating the name of the variable to use as the second dimension.
- var1T
A function used to transform var1 (e.g., log, sqrt - optional).
- var2T
A function used to transform var2 (e.g., log, sqrt - optional).
- nbins
A numeric value indicating the number of bins in both vertical and horizontal directions (default = 100).
- eps
A numeric value specifying the reachability distance (Ester et al., 1996), which correspond to the maximum distance around cluster's members (see
dbscan
).- minPts
A numeric value specifying the reachability minimum no. of points (Ester et al., 1996), which correspond to the minimum number of point per cluster (see
dbscan
).- scale
A logical value (i.e., TRUE or FALSE) indicating whether the data should be centered (i.e., values minus the mean) and scaled (divided by the standard deviation) (default = TRUE).
- na.rm
A logical value (i.e., TRUE or FALSE) indicating whether NA values should be stripped before the computation proceeds (default = TRUE).
Value
This function returns the results of the classification (actives vs. inactives) as numeric value (1 or 0, respectively) appended to each tracklet of the "tracklets" object.
References
Christian, H., (2020). fpc: Flexible Procedures for Clustering. R package version 2.2-9. https://CRAN.R-project.org/package=fpc
Ester, M., Kriegel H.P., Sander, J., Xu X., (1996). A Density-Based Algorithm for Discovering Clusters in Large Spatial Databases with Noise. Institute for Computer Science, University of Munich. Proceedings of 2nd International Conference on Knowledge Discovery and Data Mining (KDD-96).
Examples
if (FALSE) {
# Download the first dataset from the sample data repository
Path2Data <- MoveR::DLsampleData(dataSet = 1, tracker = "TRex")
Path2Data
# Import the list containing the 9 vectors classically used for further computation
trackDat <- MoveR::readTrex(Path2Data[[1]])
# infinite values that are present in the tracking output should be removed
## define the filter
filter.Inf <-
MoveR::filterFunc(
trackDat,
toFilter = "x.pos",
customFunc = function(x)
is.infinite(x)
)
### filter Infinite values
trackDat.Infilt <-
MoveR::filterTracklets(trackDat,
filter = filter.Inf,
splitCond = TRUE,
minDur = 100)
### retrieve the list of tracklets
trackdat2 <- trackDat.Infilt[[2]]
# check the tracklet
MoveR::drawTracklets(trackdat2)
# add some metric to the dataset to perform 2d clustering (speed and turning angle)
# and smooth them by computing the mean value over a 10 frames' sliding window
Tstep = 10
trackdat3 <-
MoveR::analyseTracklets(
trackdat2,
customFunc = list(
# specify a first function to compute speed over each tracklet (a modulus present within the MoveR package)
speed = function(x)
MoveR::speed(x),
# compute turning angle in radians over each tracklet (a modulus present within the MoveR package)
TurnAngle = function(x)
MoveR::turnAngle(x),
# smooth variance of turning angles
SlideVarAngle = function (y)
MoveR::slidWindow(y$TurnAngle,
Tstep = Tstep,
statistic = 'circular.var',
na.rm = TRUE),
# smooth speed
slideMeanSpeed = function (y)
MoveR::slidWindow(y$speed,
Tstep = Tstep,
statistic = 'mean',
na.rm = TRUE)
)
)
# use density based clustering to classify actives and inactives states in a 2 dimension array (here the speed and the angle variance)
trackdat3 <- MoveR::activity2(
trackdat3,
var1 = "slideMeanSpeed",
var2 = "SlideVarAngle",
var1T = log10,
nbins = 100,
eps = 0.15,
minPts = 5,
scale = TRUE,
na.rm = TRUE
)
## optional, it is possible to draw the distribution of the count in 2 dimension space
# compute the count matrix in the 2d space with the same parameter than activity2 function
trackDatL <- MoveR::convert2List(trackdat3)
outP <- MoveR::countMat(x = log10(trackDatL[["slideMeanSpeed"]]),
y = trackDatL[["SlideVarAngle"]],
groups = trackDatL[["activity2"]],
nbins = 100,
output = "matrix")
# retrieve max and min value of sqrt-transformed count over the groups for plotting
maxVal <- max(unlist(lapply(outP, function(z) max(sqrt(z)))))
minVal <- min(unlist(lapply(outP, function(z) min(sqrt(z)))))
# draw the plot using plotly (3d interactive plot)
library(plotly)
fig <- plotly::plot_ly(x=~colnames(outP[[1]]), y=~rownames(outP[[1]]), contours = list(
z = list(
show = TRUE,
start = round(minVal,-2),
project = list(z = TRUE),
end = round(maxVal,-2),
size = max(maxVal) / 10,
color = "white"
)
))
# add inactive layer
fig <- plotly::add_surface(
p = fig,
z = sqrt(outP[[1]]),
opacity = 0.8,
colorscale = "Hot",
cmin = min(sqrt(outP[[1]])),
cmax = max(sqrt(outP[[1]])),
colorbar = list(title = "inactive\ncounts (sqrt)")
)
# add active layer
fig <- plotly::add_surface(
p = fig,
z = sqrt(outP[[2]]),
opacity = 1,
colorscale = list(
c(0, 0.25, 1),
c("rgb(20,20,20)", "rgb(58,139,44)", "rgb(234,239,226)")
),
colorbar = list(title = "active\ncounts (sqrt)")
)
fig <- plotly::layout(
fig,
title = '3D density plot of activity states',
scene1 = list(
xaxis = list(title = "slideMeanSpeed (log10)"),
yaxis = list(title = "slideVarAngle"),
zaxis = list(title = "counts (sqrt)")
)
)
fig
# draw the particle' trajectory and spot the inactive moments using red dots
MoveR::drawTracklets(trackdat3,
cex.start = 0.1,
add2It = list(for (i in seq_along(trackdat3)) {
points(
trackdat3[[i]][["x.pos"]][which(trackdat3[[i]][["activity2"]] == 0)],
trackdat3[[i]][["y.pos"]][which(trackdat3[[i]][["activity2"]] == 0)],
col = "red",
pch = 19,
cex = 1.5
)
}))
}