Diff of /R/ellipsoid_body.R [000000] .. [3b2327]

Switch to unified view

a b/R/ellipsoid_body.R
1
#' @title Coarse Masking of Image from Z-slicding
2
#' @description Calculates an Ellipsoid at each slice then stacks them
3
#'
4
#' @param x Binary \code{antsImage}
5
#'
6
#' @return Array or \code{antsImage} object
7
#' @export
8
#' @importFrom ANTsRCore is.antsImage
9
#' @importFrom stats cov
10
ellipsoid_body = function(x) {
11
  bb = as.array(x)
12
  dimg = dim(bb)
13
  number_slices = dimg[3]
14
  dslice = dimg[1:2]
15
  omat = array(FALSE, dim = dimg)
16
17
  # get values that are true for ellipse
18
  ind = which(bb > 0, arr.ind = TRUE)
19
  L = lapply(dslice, seq)
20
  # same for all slices
21
  X = as.matrix(expand.grid(L))
22
23
  # need df for split
24
  ind = as.data.frame(ind)
25
  ps = split(ind, ind[,3])
26
  ps = lapply(ps, function(x){
27
    as.matrix(x[, 1:2])
28
  })
29
  # Getting mu/sigma for ellipse
30
  vals = lapply(ps, function(x){
31
    L = list(mu = colMeans(x),
32
             Sigma = cov(x))
33
  })
34
  # Taken from SIBER, but faster because no looping over solve
35
  pointsToEllipsoid2 = function(X, Sigma, mu) {
36
    eig <- eigen(Sigma)
37
    SigSqrt = eig$vectors %*% diag(sqrt(eig$values)) %*% t(eig$vectors)
38
    xtx = t(SigSqrt) %*% SigSqrt
39
    ss = solve(xtx)
40
    xx = t(t(X) - mu)
41
    Z = ss %*% t(SigSqrt) %*% t(xx)
42
    Z = t(Z)
43
  }
44
  # Taken from SIBER
45
  ellipseInOut2 = function(Z, p = 0.95, radius = NULL) {
46
    if (is.null(radius)) {
47
      radius <- stats::qchisq(p, df = ncol(Z))
48
    }
49
    inside <- rowSums(Z^2) < radius
50
    return(inside)
51
  }
52
  for ( i in seq(number_slices)) {
53
    x = vals[[i]]
54
    Z = pointsToEllipsoid2(X, Sigma = x$Sigma, mu = x$mu)
55
    inside = ellipseInOut2(Z = Z, p = 0.95)
56
    mat = array(inside, dim = dslice)
57
    omat[,,i] = mat
58
  }
59
  if (is.antsImage(x)) {
60
    omat = as.antsImage(omat, reference = x)
61
  }
62
  return(omat)
63
}