Skip to content

Obscure error when occs/bg coords fall outside envs extent #180

Description

@fdecunta

When all occs or bg coordinates fall outside the extent of envs (e.g., due to mistakenly passing coordinates in latitude-longitud order), ENMevaluate() raises an obscure error.

For example, this code uses climatic data from Patagonia and mistakenly inputs occs with lat-long (wrong order). The error is not useful:

library(terra)
library(ENMeval)

# 'example_data.csv' is attached in the issue
bad_occs <- read.csv("data/minimal_example.csv")

envs <- geodata::worldclim_global(var = "bio", res = 5, path = "data/worldclim")
## when cropped to Patagonia, swapped long-lat falls outside the map and produces an error
envs_cropped <- crop(envs, ext(-85, -35, -56, -35))

mod <- ENMevaluate(
    occs = bad_occs,
    envs = envs_cropped,
    algorithm = 'maxnet', 
    tune.args = list(fc = c("L"), rm = 1),
    partitions = "block")

Output:

*** Running initial checks... ***

* Randomly sampling 10000 background points ...
* Removed 18 occurrence localities that shared the same grid cell.
* Removed 1 occurrence points with NA predictor variable values.
* Clamping predictor variable rasters...
Error in `.rowNamesDF<-`(x, value = value) : invalid 'row.names' length

The problem starts when extracting values from envs at occs coordinates, lines 471-483

    # remove cell duplicates
    if(other.settings$removeduplicates == TRUE) {
      occs.cellNo <- terra::extract(envs, occs, cells = TRUE, ID = FALSE)
      occs.dups <- duplicated(occs.cellNo[,"cell"])
      if(sum(occs.dups) > 0) if(quiet != TRUE)
        message(paste0("* Removed ",
                       sum(occs.dups),
                       " occurrence localities that shared the same grid cell."))
      occs <- occs[!occs.dups,]
      if(!is.null(user.grp)) user.grp$occs.grp <- user.grp$occs.grp[!occs.dups]
      occs.z <- occs.cellNo[!occs.dups,-which(names(occs.cellNo) == "cell")]
    }else{
      occs.z <- terra::extract(envs, occs, ID = FALSE)
    }
 
    # bind coordinates to predictor variable values for occs and bg
    bg.z <- terra::extract(envs, bg, ID = FALSE)

In this case, swapped coordinates are so wrong that all predictors return NAs in occs.cellNo. Then, all but one row are considered duplicates and dropped. If removeduplicates == FALSE, it keeps all rows but they are just NAs. After that ENMevaluate() removes NAs. So it silently produces empty data frames for occs or bg, which later raises an error.

This can be avoided by checking that terra::extract doesn't get all NAs for occs and bg.

However, a bigger problem may be having no guard against lat-long instead of long-lat data. If the order is wrong but all the map is used, the model won't fail during checks.

I looked at how terra::vect handles this, and it uses a simple heuristic. Maybe many of these mistakes could be caught by checking that the name of the columns for occs and bg and throwing a warning.

I will open two small pull requests with those fixes in case you find them useful.

Thank you for your work!

Best,
Facundo

minimal_example.csv

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions