0

I need to integrate the area under the curve for the O-ring statistic in Rstudio. However, the package spatialEco does not report the actual values of the O-ring statistic as you would see in the Ripley's K function from the package spatstat. Here is the code to get to the point where I am at.

library('spatstat')
library('ggplot2')
library('spatialEco')

set.seed(seed=24)

radiusCluster<-100
lambdaParent<-.02
lambdaDaughter<-30
hosts<-1000
randmod<-0
dim<-2000


numbparents<-rpois(1,lambdaParent*dim)

xxParent<-runif(numbparents,0+radiusCluster,dim-radiusCluster)
yyParent<-runif(numbparents,0+radiusCluster,dim-radiusCluster)

numbdaughter<-rpois(numbparents,(lambdaDaughter))
sumdaughter<-sum(numbdaughter)



thetaLandscape<-2*pi*runif(sumdaughter)

rho<-radiusCluster*sqrt(runif(sumdaughter))


xx0=rho*cos(thetaLandscape)
yy0=rho*sin(thetaLandscape)


xx<-rep(xxParent,numbdaughter)
yy<-rep(yyParent,numbdaughter)

xx<-xx+xx0

yy<-yy+yy0
cds<-data.frame(xx,yy)
is_outlier<-function(x){
  x > dim| x < 0
}
cds<-cds[!(is_outlier(cds$xx)|is_outlier(cds$yy)),]
while (nrow(cds)<hosts){
 dif<-hosts-nrow(cds)
  extraparentxx<-sample(xxParent,dif,replace = TRUE)
  extraparentyy<-sample(yyParent,dif,replace = TRUE)
  extrathetaLandscape<-2*pi*runif(dif)
  extrarho<-radiusCluster*sqrt(runif(dif))
  newextracoodsxx<-extrarho*cos(extrathetaLandscape)
  newextracoodsyy<-extrarho*sin(extrathetaLandscape)
  extraxx<-extraparentxx+newextracoodsxx
  extrayy<-extraparentyy+newextracoodsyy
  cdsextra<-data.frame(xx=extraxx,yy=extrayy)
  cds<-rbind(cds,cdsextra)
}


sampleselect<-sample(1:nrow(cds),hosts,replace=F)
cds<-cds%>%slice(sampleselect)

randfunction<-function(x){
  x<-runif(length(x),0,dim)
}
randselect<-sample(1:nrow(cds),floor(hosts*randmod),replace=F)
cds[randselect,]<-apply(cds[randselect,],1,randfunction)

landscape<-ppp(x=cds$xx,y=cds$yy,window=owin(xrange=c(0,dim),yrange=c(0,dim)))
ggplot(data.frame(landscape))+geom_point(aes(x=x,y=y))+coord_equal()+theme_minimal()

ostat<-o.ring(landscape,inhomogenous=FALSE)

This produces the O-ring plot: enter image description here

Is it possible to integrate this plot to estimate the area under this curve?

OpenSauce
  • 354
  • 2
  • 14
  • sure, check out this answer: https://stackoverflow.com/questions/4954507/calculate-the-area-under-a-curve I couldn't run your code, but it should essentially be: `sum( diff(landscape$xx) * rollmean( landscape$yy, 2 ) )` – Sirius Apr 08 '21 at 14:23
  • Hi Sirius, thanks for your suggestion, the problem is that I do not know how to get the r and corresponding O-ring(r) values (see axes above) from the statistical tool available in spatialEco. It does not report the values as you would see in spatstat for example. – OpenSauce Apr 08 '21 at 14:37
  • What was the error when trying to run my code? Did you install the packages mentioned above? – OpenSauce Apr 08 '21 at 14:39
  • Sorry I didn't paste all of your code for some reason, it likely would run – Sirius Apr 08 '21 at 17:47

1 Answers1

1

If you peek inside the o.ring function, you see this:


## > o.ring

function (x, inhomogeneous = FALSE, ...) 
{
    if (inhomogeneous) {
        g <- spatstat.core::pcfinhom(x, ...)
    }
    else {
        g <- spatstat.core::pcf(x, ...)
    }
    lambda <- summary(x)$intensity
    O <- spatstat.core::eval.fv(lambda * g)
    graphics::plot(O, ylab = "O-ring(r)", main = "O-ring")
}

Now execute these steps yourself:


x <- landscape
g <- spatstat.core::pcf(x)
lambda <- summary(x)$intensity
O <- spatstat.core::eval.fv(lambda * g)

print.data.frame(head(O))

Outputs:


> print.data.frame( head(O) )
          r    theo       trans         iso
1 0.0000000 0.00025         Inf         Inf
2 0.9765625 0.00025 0.002681005 0.002671475
3 1.9531250 0.00025 0.001666361 0.001659885
4 2.9296875 0.00025 0.001351382 0.001345655
5 3.9062500 0.00025 0.001212683 0.001207095
6 4.8828125 0.00025 0.001141121 0.001135419

I guess, though I 'd need to look at plot.fv to be sure, that trans and iso is either of the solid or dashed line. Do you know which one you want to integrate?

In any case, these are your respective areas:


## filter out the Inf values
my.O <- O %>% filter( is.finite(trans) & is.finite(iso) )

library(zoo)

sum( diff(my.O$r) * rollmean( my.O$trans, 2 ) )

sum( diff(my.O$r) * rollmean( my.O$iso, 2 ) )

Sirius
  • 5,224
  • 2
  • 14
  • 21
  • Sirius, this answer is brilliant! Thank you, you're a genius. The plot is identical. I will most likely be using the isotropic edge correction method. – OpenSauce Apr 09 '21 at 12:23
  • 1
    Thank you! good debugging skills is something you develop over time, and worth their weight in gold. – Sirius Apr 09 '21 at 12:26
  • Hi again Sirius, the method of integration that you've given above with the roll mean, what is this integration method called exactly? I intend to solve numerically a complex integral by multiplying seperate terms and applying this method. Any explanation about this would be great! – OpenSauce Apr 16 '21 at 11:36
  • Np! See the question I link to in my first comment to your question. There the answerer mentions trapezium figures, and that's exactly it. by the each increment step on the x-axis, by the average of two neighboring y-values, you calculate the area of the trapezium that they span. See here: https://en.wikipedia.org/wiki/Trapezoidal_rule . A _rolling_ average of two points achieves exactly this. Although it certainly isn't obvoius that's the reason why it is being used. – Sirius Apr 16 '21 at 17:15
  • A word dropped out of my comment above.. "by multiplying each increment on the x axis by the average value of the corresponding two y values" ... Etc – Sirius Apr 17 '21 at 12:37
  • Brilliant Sirius, I've added the trapezoidal rule as a page on my OneNote. You're the best! – OpenSauce May 13 '21 at 15:29