Search code examples
rterra

CLHS throws error "not a matrix" in R (possible bug?)


I am trying to create a forest inventory plot network to calibrate a lidar dataset to predict forest biometrics. To ensure the plot network represents the full distribution of tree heights present in the lidar coverage, I am using a conditioned Latin Hypercube Sampling approach using the clhs() function in the "clhs" package. I am using a large random sample of pixels from a canopy height model raster I created as the sample space that will be divided into marginal strata for the conditioned Latin Hypercube Sampling. Following the instruction in the package documentation, I am converting my sampled pixels into a point vector using the "sf" package. However, when I run the clhs::clhs() routine, I get an error:

Error: Not a matrix.

I am confused by this because the clhs() documentation specifically mentions that "sf" points are accepted input. If I coerce the data to a matrix using as.matrix(), I get an error saying that matrices are not accepted as an input. I have also isolated this to the primary input (argument x in clhs()) by accepting all defaults for the parameterization of the Simulated Annealing algorithm. Is this possibly a bug?

Below is the reproducible example:

##loading necessary packages##
library(clhs)
library(terra)
library(sf)

##For reproducibility##
set.seed(78)

##Creating fake raster of tree heights##
fake_rast<-rast(xmin=-123.5, xmax=123.0, ymin=44.5, ymax=45.0, nrow=200, ncol=200, crs="EPSG:4326")
values(fake_rast)<-rnorm(40000, 35, 10)

##Sampling the raster and converting to sf##
smp<-spatSample(fake_rast, 500, as.points=TRUE, na.rm=TRUE, replace=FALSE) %>% st_as_sf()

##Conditioned Latin Hypercube##
#Accepting all Metropolis-Hastings Defaults and Simulated Annealing Defaults##
clhs.test<-clhs(x=smp, size=n)

#Setting all Metropolis-Hastings Defaults and Simulated Annealing Defaults##
n<-50
mi<-NULL
temp<-100
lc<-10
ol<-0.01
td<-0.9


clhs.test<-clhs(x=smp, size=n, temp=temp, iter=lc*log(ol/temp)/log(td), 
                obj.limit=ol, tdecrease=td, length.cycle=lc, must.include=mi,
                use.cpp=TRUE, simple=FALSE)


Solution

  • Turns out this was as straightforward of any error message as it gets, and had I been thinking logically about the HYPERCUBE part of this method, I would have realized I need multiple dimensions to run a CLHS. Instead I only have one dimension, which would be suited to blocking rather than a latin hypercube. Adding additional fake dimension resolved the error. Reproducible solution below:

    ##loading necessary packages##
    library(clhs)
    library(terra)
    library(sf)
    
    ##For reproducibility##
    set.seed(78)
    
    ##Creating fake raster of tree heights##
    blank<-rast(xmin=-123.5, xmax=123.0, ymin=44.5, ymax=45.0, nrow=200, ncol=200, crs="EPSG:4326")
    fake_rast1<-blank
    fake_rast2<-blank
    fake_rast3<-blank
    values(fake_rast1)<-rnorm(40000, 35, 10)
    values(fake_rast2)<-rnorm(40000, 25, 5)
    values(fake_rast3)<-rnorm(40000, 15, 2)
    
    fake_rast<-c(fake_rast1, fake_rast2, fake_rast3)
    
    ##Sampling the raster and converting to sf##
    smp<-spatSample(fake_rast, 500, as.points=TRUE, na.rm=TRUE, replace=FALSE) %>% st_as_sf()
    
    
    #Setting all Metropolis-Hastings Defaults and Simulated Annealing Defaults##
    n<-50
    mi<-NULL
    temp<-100
    lc<-10
    ol<-0.01
    td<-0.9
    
    
    clhs.test<-clhs(x=smp, size=n, temp=temp, iter=lc*log(ol/temp)/log(td), 
                    obj.limit=ol, tdecrease=td, length.cycle=lc, must.include=mi,
                    use.cpp=TRUE, simple=FALSE)