nonsensical Bhattacharyya coefficient values in koala home range overlap

8 views
Skip to first unread message

Lyn Brown

unread,
Jan 6, 2026, 12:00:50 AM (5 days ago) Jan 6
to ctmm R user group

Hi there,

I wanted to calculate the home range overlap for koalas. I was able to output a matrix of overlap values, which I thought there is supposed to be the Bhattacharyya coefficient ranging from zero to one. However, my values range from 0.08 to 21,000. This seems like it might be the raw area in squared meters that is shared between koalas. 21,0000 squared meters would be 2.1 hectares, which is reasonable for this species.

I'm not sure why I am getting this output when I specified the method in the overlap function as “Bhattacharyya”.

You'll see in my code, that I have overlap_matrix = overlap(AKDES_full),  but I had also tried overlap(AKDES_full, method = "Bhattacharyya"), which gave the same output.

As another potential fix, I tried  the code directly below this text, as per one of the help pages and a post by Allie Anderson.

AKDE_lst <- purrr::map2(tel, FITS,

            ~akde(.x, .y[[1]], #top model

                 grid = ref_grid))

 

overlap_matrix_1st = overlap(AKDES_1st)

 

However, I get the error message in this case that Error in `purrr::map2()`:

 In index: 1.

 With name: Abigail.

Caused by error in `akde()`:

! Data and models not in the same coordinate system.

 Even though, I have checked and my projection is the same for my telemetry object, list of fitted models, and utilization distributions, which I called “AKDES_full” in my code. I also formed a reference grid when calculating my AKDEs, and double checked that across all animals, the same reference grid and projection were used.

I followed working examples in this help group, specifically one posted by Allie Anderson  about creating a reference grid, and ensuring that I first project with my telemetry object, and then use that telemetry object to create the fitted models so they would all have the same projection.

I'm not sure how to extract the Bhattacharyya coefficients.

Any help is appreciated.

Minimal code is below. I can e-mail more detailed code if that is helpful.

######################FOR HR OVERLAP##################################

#1 Extract projection

PROJ <- ctmm::projection(tel[[1]])

 

#2 Force that projection onto ALL telemetry

tel <- lapply(tel, function(tel) {

  ctmm::projection(tel) <- PROJ

  tel

})

 

#3 then fit models

#TM

#parallel code for estimating fits

n.cores <- detectCores() - 1 

cl <- makeCluster(n.cores) 

registerDoParallel(cl) 

 

#names fits during loop

FITS <- foreach(id = names(tel), .packages = "ctmm") %dopar% {

  setNames(

    list({

      GUESS <- ctmm.guess(tel[[id]], interactive = FALSE)

      ctmm.select(tel[[id]], GUESS, trace = 2)

    }),

    id

  )

}

 

FITS <- unlist(FITS, recursive = FALSE)

 

 

stopCluster(cl)

rm(n.cores, cl)

 

saveRDS(FITS, "../data/FITS.rds")

 

#4 ref grid

# -----------------------------

#Build unified reference grid across all animals allie anderson

# -----------------------------

 

# Use ctmm-native extent

grid_extent <- ctmm::extent(tel)

 

# Compute ranges

x_range <- diff(grid_extent$x)

y_range <- diff(grid_extent$y)

 

# Buffer (used 5% — both are valid)

buffer_factor <- 0.05

 

buffered_extent <- list(

  x = c(grid_extent$x[1] - x_range * buffer_factor,

        grid_extent$x[2] + x_range * buffer_factor),

  y = c(grid_extent$y[1] - y_range * buffer_factor,

        grid_extent$y[2] + y_range * buffer_factor)

)

 

# Define grid resolution (meters, since UTM)

res <- 200 #did RAM calculation to come up with 200. default from allie =100

 

x_seq <- seq(buffered_extent$x[1], buffered_extent$x[2], by = res)

y_seq <- seq(buffered_extent$y[1], buffered_extent$y[2], by = res)

 

ref_grid <- list(x = x_seq, y = y_seq)

 

#5 akdes

AKDES_full <- lapply(names(tel), function(id) {

  akde(

    tel[[id]],

    FITS[[id]],

    weights = TRUE,

    debias = TRUE,

    grid = ref_grid

  )

})

names(AKDES_full) <- names(tel)

 

#6 overlap calculate

overlap_matrix = overlap(AKDES_full)

#output overlap matrix as df

overlap_matrix.df <- overlap_matrix$DOF

overlap_matrix.df <- cbind(

  Koala1 = rownames(overlap_matrix.df), as.data.frame(overlap_matrix.df)

)

 

#7. check uds were normalized with ref grid

 

#ref grid?

sapply(AKDES_full, function(x) paste(dim(x$PDF), collapse = "x"))

#projection same across inds?

sapply(AKDES_full, function(x) ctmm::projection(x))

#projection same for FITS, tel, UDs?

projection(FITS)

projection(tel)

projection(AKDES_full)

#yes -- all are "+proj=utm +zone=56 +south +ellps=GRS80 +units=m +no_defs"

Reply all
Reply to author
Forward
0 new messages