# This file includes my own functions for diameter distribution modeling. # You are welcome to use them but I take no responsibuility about inpropewr functioning or # wrong results. The functions come absolute with no warranty. # Reynolds error index # d includes true diameters, cdf is a function returning the unweighted cdf # power gives the weights (2 gives BA weight, 0 the unweighted), # dlim the range of diameters. # cwidth the class width (make sure dlim is a multiple of dlim). errind<-function(d,cdf=function(x) pweibull(x,5,20),power=0,dlim=c(-20,80),cwidth=2) { limits<-seq(dlim[1],dlim[2],cwidth) n<-length(limits)-1 means<-(limits[-1]+limits[-(n+1)])/2 dp<-d^power sumdp<-sum(dp) ftrue<-sapply(1:n,function(i) sum(dp[d>=limits[i]&d0, lambda>ksi # ksi=minimum, lambda=maximum, sigma controls curtosis and myy skewness. dll<-function(x,lambda,sigma,ksii,myy) { sigma<-exp(sigma)/(1+exp(sigma)) f<-(lambda-ksii)/sigma* 1/((x-ksii)*(lambda-x))* 1/(exp(-myy/sigma)*((x-ksii)/(lambda-x))^(1/sigma)+ exp(myy/sigma)*((x-ksii)/(lambda-x))^(-1/sigma)+2) f[x<=ksii|x>=lambda]<-0 f } # negative log likelihood nLLll<-function(x,lambda,sigma,ksii,myy) { # cat(log(dll(x,lambda,sigma,ksii,myy)),"\n") value<--sum(log(dll(x,lambda,sigma,ksii,myy))) if (value==Inf) value<-10^16 cat(lambda,sigma,ksii,myy,value,"\n") value } # derivatives of neg ll # theta=c(lambda,sigma,ksii,myy) gradnLLll<-function(x,theta) { l<-theta[1] s<-theta[2] k<-theta[3] m<-theta[4] awful<-exp(-m/s)*((x-k)/(l-x))^(1/s)+exp(m/s)*((l-x)/(x-k))^(1/s)+2 c( # with respect to lambda sum(-1/(l-k)+1/(l-x)+ 1/awful* (-exp(-m/s)*(1/s)*((x-k)/(l-x))^((1-s)/s)* (x-k)*(l-x)^(-2)+ +exp(m/s)* (1/s)*((x-k)/(l-x))^((-1-s)/s)*(x-k)*(l-x)^(-2))), # with respect to sigma sum(1/s+ 1/awful* (-(exp(-m)*((x-k)/(l-x)))^(1/s)*(-m+log((x-k)/(l-x)))*s^(-2)+ -(exp(m)*((l-x)/(x-k)))^(1/s)*(m+log((l-x)/(x-k)))*s^(-2))), #with respect to ksii sum(1/(l-k)-1/(x-k)+ 1/awful* (-exp(-m/s)*(1/s)*((x-k)/(l-x))^((1-s)/s)/(l-x)+ exp(m/s)*(1/s)*((x-k)/(l-x))^((-1-s)/s)/(l-x))), # with respect to myy sum(1/awful* (((x-k)/(l-x))^(1/s)*exp(-m/s)*(-1/s)+ ((x-k)/(l-x))^(-1/s)*exp(m/s)*(1/s))) ) } # cdf of logit-logistic distribution pll<-function(x,lambda,sigma,ksii,myy) { sigma<-exp(sigma)/(1+exp(sigma)) F<-1/(1+exp(myy/sigma)*((x-ksii)/(lambda-x))^(-1/sigma)) F[x<=ksii]<-0 F[x>=lambda]<-1 F } # a function for fitting logit-logistic distribution to tree diameter data. fitll<-function(d,start=NA) { ll<-function(lambda,sigma,ksii,myy) nLLll(d,lambda,sigma,ksii,myy) if (is.na(start)) start<-list(lambda=max(d)+5,sigma=0.5,ksii=max(0,min(d)-2),myy=0) grad<-function(theta) gradnLLll(d,theta) est<-try(mle(ll,gr=grad,method="L-BFGS-B",start=start,lower=c(max(d)+0.1,0.1,0,-5),upper=c(45,0.999,max(0,min(d)-0.1),5),control=list(maxit=200))) if (class(est)=="try-error") list(par=rep(NA,4),neg2LL=NA,conv=NA) else list(par=coef(est),neg2LL=2*attributes(est)$min,conv=attributes(est)$details$convergence) } # Another function for the same purpose # sigma is bounded using logit transformation fitll<-function(d,start=NA) { ll<-function(lambda,sigma,ksii,myy) nLLll(d,lambda,sigma,ksii,myy) if (is.na(start)) start<-list(lambda=max(d)+5,sigma=0,ksii=max(0,min(d)-2),myy=0) est<-try(mle(ll,method="L-BFGS-B",start=start,lower=c(max(d)+0.1,-Inf,0,-5),upper=c(45,3.5,max(0,min(d)-0.1),5),control=list(maxit=200))) if (class(est)=="try-error") list(par=rep(NA,4),neg2LL=NA,conv=NA) else list(par=coef(est),neg2LL=2*attributes(est)$min,conv=attributes(est)$details$convergence) } # quantile function of the logit-logistic distribution qll<-function(p,lambda,sigma,ksii,myy) { apu<-sapply(1:length(p),function (i) updown(l=ksii,u=lambda, fn=function(x) pll(x,lambda,sigma,ksii,myy)-p[i],crit=10)$par) apu } # random number generation from the logit-logistic distribution rll<-function(n,lambda,sigma,ksii,myy) { qll(runif(n),lambda,sigma,ksii,myy) } # the relatinship between N and G when tree diameter follows the logit-logistic distribution npergll<-function(lambda,sigma,ksii,myy) { 1/integrate(function(x) pi*x^2/40000*dll(x,lambda,sigma,ksii,myy),ksii,lambda)$value } # Rennolls&Wang parameterization of Johnsons SB distribution # lamda=maximum, not range # desity dsb<-function(x,ksi,lambda,delta,gamma) { value<-rep(NA,length(x)) value[x>ksi&xksi&xksi&xksi&xksi&x=lambda]<-0 value } # c.d.f psb<-function(x,ksi,lambda,delta,gamma) { y<-rep(NA,length(x)) y[x<=ksi]<-0 y[x>=lambda]<-1 y[x>ksi&xksi&x