rsentinel2

Downloading Sentinel 2 with rsat package in R produces error "argument "espa_orders" is missing, with no default"


I am attempting to download Sentinel 2 data in R using the rsat package which leverages the application programming interface to Copernicus' Dataspace web service. The code to create a region of interest and a time period of inquiry, new_rtoi(), as well as the code to search Dataspace, rsat_search(), is really straightforward and intuitive, which I very much appreciate. However, when I make the final call to rsat_download(), I get the following error:

Ordering on ESPA platform...
Error in (new("refMethodDef", .Data = function (espa_orders, db_path,  : 
  argument "espa_orders" is missing, with no default

I looked through the documentation for the rsat_download() function, and "espa_orders" is not an argument. I am wondering if this a bug in an internal function. Below is my reproducible example:

library(rsat)
library(terra)
library(sf)
library(tmap)
library(tmaptools)


xmin<-538078.1
xmax<-866945.5  
ymin<-773531.3
ymax<-1436377.3

AOI_ext<-ext(xmin, xmax, ymin, ymax)

AOI<-AOI_ext %>% st_bbox() %>% st_as_sfc() %>% st_as_sf(crs=6557) 


tmap_mode("view")

tm_shape(AOI)+
  tm_polygons(border.col="magenta", alpha=0, col=NA, lwd=2)+
  tm_basemap(server = providers$Esri.WorldImagery)

toi<-as.Date("2023-04-27")

db.path <- file.path(tempdir(),"database_test")
ds.path <- file.path(tempdir(),"datasets_test")

if(!dir.exists(db.path)){
  dir.create(db.path)
}

if(!dir.exists(ds.path)){
  dir.create(ds.path)
}

April<-new_rtoi(name="April_test2", region=AOI, db_path=db_path, rtoi_path = ds_path)
searchit<-rsat_search(region=April, product="S2MSI1C", dates=toi)
rsat_download(searchit, db_path=db_path)

Solution

  • I looked at the source code of rsat_download() and it looks like this issue arises from unnecessary subsetting of a negated condition for the particular satellite dataset application programming interface. Specifically, the original code filters the application programming interfaces to search like this:

        #filter records
        usgs <- x[get_api_name(x)%in%"usgs"]
        x <- x[!(get_api_name(x)%in%"usgs")]
        dataspace <- x[get_api_name(x)%in%"dataspace"]
        x <- x[!(get_api_name(x)%in%"dataspace")]
        lpdaac <- x[get_api_name(x)%in%"lpdaac"]
        x <- x[!(get_api_name(x)%in%"lpdaac")]
    

    if you removed the negated subsets so that the chunk of code looks like this:

      dataspace <- x[get_api_name(x)%in%"dataspace"]
      usgs <- x[get_api_name(x)%in%"usgs"]
      lpdaac <- x[get_api_name(x)%in%"lpdaac"]
    

    you'll get an error specifying that there is no method for get_api_name() for rtoi signature. This can be overcome by adding a this call x<-records(x) at the top of the revised chunk so that it looks like this

      x<-records(x)
      dataspace <- x[get_api_name(x)%in%"dataspace"]
      usgs <- x[get_api_name(x)%in%"usgs"]
      lpdaac <- x[get_api_name(x)%in%"lpdaac"]
    

    The full hack to rsat_download() that worked for me to get around this bug was

    rsat_download2<-function(x, db_path, verbose = FALSE, parallel=FALSE, ...) {
      require(rsat)
      
      args <- list(...)
    
      if (missing(db_path)){
        db_path <- get_database(x)
        if(db_path==""){
          stop("db_path or global environment database needed for image downloading.")
        }
      }
      
    # filter records
      x<-records(x)
      dataspace <- x[get_api_name(x)%in%"dataspace"]
      usgs <- x[get_api_name(x)%in%"usgs"]
      lpdaac <- x[get_api_name(x)%in%"lpdaac"]
      
    # run download
      if(parallel){
        functions_list <- list(
         list(func = connection$getApi("lpdaac")$download_lpdaac_records,
               args = list(lpdaac_records=lpdaac,db_path=db_path,verbose=verbose,...)),
          list(func = rsat:::connection$getApi("dataspace")$dataspace_download_records,
               args = list(records=dataspace,db_path=db_path,verbose=verbose,...)),
          list(func = connection$getApi("usgs")$espa_order_and_download,
               args = list(usgs=usgs,db_path=db_path,verbose=verbose,...))
        )
        null.list <-mclapply(functions_list, function(entry) {
          do.call(entry$func, entry$args)
        }, mc.cores = 3)
      }else{
        functions_list <- list(
          list(func = rsat:::connection$getApi("usgs")$order_usgs_records,
               args = list(espa_orders=usgs,db_path=db_path,verbose=verbose,...)),
          list(func = rsat:::connection$getApi("lpdaac")$download_lpdaac_records,
               args = list(lpdaac_records=lpdaac,db_path=db_path,verbose=verbose,...)),
          list(func = rsat:::connection$getApi("dataspace")$dataspace_download_records,
               args = list(records=dataspace,db_path=db_path,verbose=verbose,...)),
          list(func = rsat:::connection$getApi("usgs")$download_espa_orders,
              args = list(espa.orders=usgs,db_path=db_path,verbose=verbose,...))
        )
        null.list <- lapply(functions_list, function(entry) {
          do.call(entry$func, entry$args)
        })
      }
    }
    
    

    And here is a working reproducible example with the hacked rsat_download2() above:

    library(rsat)
    library(terra)
    library(sf)
    library(tmap)
    library(tmaptools)
    
    
    xmin<-538078.1
    xmax<-866945.5  
    ymin<-773531.3
    ymax<-1436377.3
    
    AOI_ext<-ext(xmin, xmax, ymin, ymax)
    
    AOI<-AOI_ext %>% st_bbox() %>% st_as_sfc() %>% st_as_sf(crs=6557) 
    
    
    tmap_mode("view")
    
    tm_shape(AOI)+
      tm_polygons(border.col="magenta", alpha=0, col=NA, lwd=2)+
      tm_basemap(server = providers$Esri.WorldImagery)
    
    toi<-as.Date("2023-04-27")
    
    db.path <- file.path(tempdir(),"database_test")
    ds.path <- file.path(tempdir(),"datasets_test")
    
    if(!dir.exists(db.path)){
      dir.create(db.path)
    }
    
    if(!dir.exists(ds.path)){
      dir.create(ds.path)
    }
    
    April<-new_rtoi(name="April_test2", region=AOI, db_path=db.path, rtoi_path = ds.path)
    rsat_search(region=April, product="S2MSI1C", dates=toi)
    rsat_download2(April, db_path=db.path)