##################################################################################################################
#########  WHO Child Growth Standards                                                                        #####
#########  Department of Nutrition for Health and Development                                                #####
#########  World Health Organization                                                                         #####
#########  Last modified on 07/10/2013     -     Developed using R version 3.0.1 (2013-05-16)                #####
#########  This code corcerns the standard approach for the prevalences, i.e. the calculation of the         #####
#########  prevalences takes into account all the valid (non-missing) z-scores for each of the indicators.   #####
##################################################################################################################

##################################################################################################################
#########  Function for calculating the z-scores and prevalences for a nutritional survey                    #####
##################################################################################################################

########################################################################
#### Auxiliar functions
########################################################################

#############################################################################
##### Prevalence calculation for the upper bound and corresponding 95% C.I.
#############################################################################

#### Without oedema (for head circumference-for-age and arm circumferecen-for-age)

prevph.L <- function(a,x,w) {
   ph <- sum((x > a)*w,na.rm=T)/sum((!is.na(x))*w,na.rm=T)
   aux <- 1.96*sqrt(ph*(1-ph)/sum((!is.na(x))*w,na.rm=T))+(1/(2*sum((!is.na(x))*w,na.rm=T)))
   vec <- c(rounde(sum((!is.na(x))*w,na.rm=T),digits=0),rounde(c(ph, max(0,ph-aux), ph+aux)*100,digits=1))
   return(vec)
   }

#### With oedema (only for weight-for-length/height and bmi-for-age)

prevph <- function(a,x,w,f) {
   f<-as.character(f)
   ph <- sum((x > a)*w,na.rm=T)/sum(((!is.na(x)) | (f=="y"))*w,na.rm=T)
   aux <- 1.96*sqrt(ph*(1-ph)/sum(((!is.na(x)) | (f=="y"))*w,na.rm=T))+(1/(2*sum(((!is.na(x)) | (f=="y"))*w,na.rm=T)))
   vec <- c(rounde(sum(((!is.na(x)) | (f=="y"))*w,na.rm=T),digits=0),rounde(c(ph, max(0,ph-aux), ph+aux)*100,digits=1))
   return(vec)
   }

#############################################################################
##### Prevalence calculation for the lower bound and corresponding 95% C.I.
#############################################################################

#### Without oedema (for length/height-for-age)

prevnh.L <- function(a,x,w) {
   ph <- sum((x < a)*w,na.rm=T)/sum((!is.na(x))*w,na.rm=T)
   aux <- 1.96*sqrt(ph*(1-ph)/sum((!is.na(x))*w,na.rm=T))+(1/(2*sum((!is.na(x))*w,na.rm=T)))
   vec <- c(rounde(sum((!is.na(x))*w,na.rm=T),digits=0),rounde(c(ph, max(0,ph-aux), ph+aux)*100,digits=1))
   return(vec)
   }

#### With oedema  (for all weight-related indicators)

prevnh <- function(a,x,w,f) {
   f<-as.character(f)
   ph <- sum((x < a | f=="y")*w,na.rm=T)/sum(((!is.na(x)) | (f=="y"))*w,na.rm=T)
   aux <- 1.96*sqrt(ph*(1-ph)/sum(((!is.na(x)) | (f=="y"))*w,na.rm=T))+(1/(2*sum(((!is.na(x)) | (f=="y"))*w,na.rm=T)))
   vec <- c(rounde(sum(((!is.na(x)) | (f=="y"))*w,na.rm=T),digits=0),rounde(c(ph, max(0,ph-aux), ph+aux)*100,digits=1))
   return(vec)
   }

###########################################
#### Weighted mean  and standard deviation
###########################################

wmean <- function(x,w) { return(rounde(sum(x*w,na.rm=T)/sum(w[!is.na(x)]),digits=2) )  }

wsd <- function(x,w) {
   mh <- sum(x*w,na.rm=T)/sum((!is.na(x))*w,na.rm=T)
   sdh<-ifelse(length(x[!is.na(x)])>0,rounde(sqrt(sum(((x-mh)^2)*w,na.rm=T)/(sum((!is.na(x))*w,na.rm=T) - 1)),digits=2),NA)
   return( sdh )
   }

######################################################################################
#### Rounding function - SPlus rounding function uses the nearest even number rule
######################################################################################

rounde <- function(x,digits=0) {
	expo<-10^digits
	return(ifelse(abs(x*expo) - floor(abs(x*expo)) < 0.5, sign(x*expo) * floor(abs(x*expo)), sign(x*expo) * (floor(abs(x*expo)) + 1))/expo)
}

######################################################################################
### Function for calculating individual Length-for-age z-scores
######################################################################################

calc.zlen<-function(mat,lenanthro){

for(i in 1:length(mat$age.days)) {

	if(!is.na(mat$age.days[i]) & mat$age.days[i]>=0 & mat$age.days[i]<=1856) {

		l.val<-lenanthro$l[lenanthro$age==mat$age.days[i] & lenanthro$sex==mat$sex[i]]
		m.val<-lenanthro$m[lenanthro$age==mat$age.days[i] & lenanthro$sex==mat$sex[i]]
		s.val<-lenanthro$s[lenanthro$age==mat$age.days[i] & lenanthro$sex==mat$sex[i]]
		mat$zlen[i]<-(((mat$clenhei[i]/m.val)^l.val)-1)/(s.val*l.val)

	}	else mat$zlen[i]<- NA

}
return(mat)
}

######################################################################################
### Function for calculating individual Head circumference-for-age z-scores
######################################################################################

calc.zhc<-function(mat,hcanthro){

for(i in 1:length(mat$age.days)) {

	if(!is.na(mat$age.days[i]) & mat$age.days[i]>=0 & mat$age.days[i]<=1856) {

		l.val<-hcanthro$l[hcanthro$age==mat$age.days[i] & hcanthro$sex==mat$sex[i]]
		m.val<-hcanthro$m[hcanthro$age==mat$age.days[i] & hcanthro$sex==mat$sex[i]]
		s.val<-hcanthro$s[hcanthro$age==mat$age.days[i] & hcanthro$sex==mat$sex[i]]
		mat$zhc[i]<-(((mat$headc[i]/m.val)^l.val)-1)/(s.val*l.val)

	}	else mat$zhc[i]<- NA

}
return(mat)
}

######################################################################################
### Function for calculating individual Weight-for-age z-scores
######################################################################################

calc.zwei<-function(mat,weianthro){

for(i in 1:length(mat$age.days)) {

	if(!is.na(mat$age.days[i]) & mat$age.days[i]>=0 & mat$age.days[i]<=1856 & mat$oedema[i]!="y") {

		l.val<-weianthro$l[weianthro$age==mat$age.days[i] & weianthro$sex==mat$sex[i]]
		m.val<-weianthro$m[weianthro$age==mat$age.days[i] & weianthro$sex==mat$sex[i]]
		s.val<-weianthro$s[weianthro$age==mat$age.days[i] & weianthro$sex==mat$sex[i]]

		mat$zwei[i]<-(((mat$weight[i]/m.val)^l.val)-1)/(s.val*l.val)
		if(!is.na(mat$zwei[i]) & mat$zwei[i]>3) {
						sd3pos<- m.val*((1+l.val*s.val*3)^(1/l.val))
						sd23pos<- sd3pos- m.val*((1+l.val*s.val*2)^(1/l.val))
						mat$zwei[i]<- 3+((mat$weight[i]-sd3pos)/sd23pos)
						}
		if(!is.na(mat$zwei[i]) & mat$zwei[i]< (-3)) {
						sd3neg<- m.val*((1+l.val*s.val*(-3))**(1/l.val))
						sd23neg<- m.val*((1+l.val*s.val*(-2))**(1/l.val))-sd3neg
						mat$zwei[i]<- (-3)+((mat$weight[i]-sd3neg)/sd23neg)
						}

		} else mat$zwei[i]<-NA
}
return(mat)
}

######################################################################################
### Function for calculating individual Arm circumference-for-age z-scores
######################################################################################

calc.zac<-function(mat,acanthro){

for(i in 1:length(mat$age.days)) {

	if(!is.na(mat$age.days[i]) & mat$age.days[i]>=91 & mat$age.days[i]<=1856) {

		l.val<-acanthro$l[acanthro$age==mat$age.days[i] & acanthro$sex==mat$sex[i]]
		m.val<-acanthro$m[acanthro$age==mat$age.days[i] & acanthro$sex==mat$sex[i]]
		s.val<-acanthro$s[acanthro$age==mat$age.days[i] & acanthro$sex==mat$sex[i]]
		mat$zac[i]<-(((mat$armc[i]/m.val)^l.val)-1)/(s.val*l.val)
		if(!is.na(mat$zac[i]) & mat$zac[i]>3) {
						sd3pos<- m.val*((1+l.val*s.val*3)^(1/l.val))
						sd23pos<- sd3pos- m.val*((1+l.val*s.val*2)^(1/l.val))
						mat$zac[i]<- 3+((mat$armc[i]-sd3pos)/sd23pos)
						}
		if(!is.na(mat$zac[i]) & mat$zac[i]< (-3)) {
						sd3neg<- m.val*((1+l.val*s.val*(-3))**(1/l.val))
						sd23neg<- m.val*((1+l.val*s.val*(-2))**(1/l.val))-sd3neg
						mat$zac[i]<- (-3)+((mat$armc[i]-sd3neg)/sd23neg)
						}

		} else mat$zac[i]<-NA

}
return(mat)
}

######################################################################################
### Function for calculating individual Triceps skinfold-for-age z-scores
######################################################################################

calc.zts<-function(mat,tsanthro){

for(i in 1:length(mat$age.days)) {

	if(!is.na(mat$age.days[i]) & mat$age.days[i]>=91 & mat$age.days[i]<=1856) {

		l.val<-tsanthro$l[tsanthro$age==mat$age.days[i] & tsanthro$sex==mat$sex[i]]
		m.val<-tsanthro$m[tsanthro$age==mat$age.days[i] & tsanthro$sex==mat$sex[i]]
		s.val<-tsanthro$s[tsanthro$age==mat$age.days[i] & tsanthro$sex==mat$sex[i]]

		mat$zts[i]<-(((mat$triskin[i]/m.val)^l.val)-1)/(s.val*l.val)
		if(!is.na(mat$zts[i]) & mat$zts[i]>3) {
						sd3pos<- m.val*((1+l.val*s.val*3)^(1/l.val))
						sd23pos<- sd3pos- m.val*((1+l.val*s.val*2)^(1/l.val))
						mat$zts[i]<- 3+((mat$triskin[i]-sd3pos)/sd23pos)
						}
		if(!is.na(mat$zts[i]) & mat$zts[i]< (-3)) {
						sd3neg<- m.val*((1+l.val*s.val*(-3))**(1/l.val))
						sd23neg<- m.val*((1+l.val*s.val*(-2))**(1/l.val))-sd3neg
						mat$zts[i]<- (-3)+((mat$triskin[i]-sd3neg)/sd23neg)
						}

		} else mat$zts[i]<-NA

}

return(mat)
}

######################################################################################
### Function for calculating individual Subscapular skinfold-for-age z-scores
######################################################################################

calc.zss<-function(mat,ssanthro){

for(i in 1:length(mat$age.days)) {

	if(!is.na(mat$age.days[i]) & mat$age.days[i]>=91 & mat$age.days[i]<=1856) {

		l.val<-ssanthro$l[ssanthro$age==mat$age.days[i] & ssanthro$sex==mat$sex[i]]
		m.val<-ssanthro$m[ssanthro$age==mat$age.days[i] & ssanthro$sex==mat$sex[i]]
		s.val<-ssanthro$s[ssanthro$age==mat$age.days[i] & ssanthro$sex==mat$sex[i]]

		mat$zss[i]<-(((mat$subskin[i]/m.val)^l.val)-1)/(s.val*l.val)
		if(!is.na(mat$zss[i]) & mat$zss[i]>3) {
						sd3pos<- m.val*((1+l.val*s.val*3)^(1/l.val))
						sd23pos<- sd3pos- m.val*((1+l.val*s.val*2)^(1/l.val))
						mat$zss[i]<- 3+((mat$subskin[i]-sd3pos)/sd23pos)
						}
		if(!is.na(mat$zss[i]) & mat$zss[i]< (-3)) {
						sd3neg<- m.val*((1+l.val*s.val*(-3))**(1/l.val))
						sd23neg<- m.val*((1+l.val*s.val*(-2))**(1/l.val))-sd3neg
						mat$zss[i]<- (-3)+((mat$subskin[i]-sd3neg)/sd23neg)
						}

		} else mat$zss[i]<-NA
}

return(mat)
}

######################################################################################
### Function for calculating individual Weight-for-length/height z-scores
######################################################################################

calc.zwfl<-function(mat,wflanthro,wfhanthro){

for(i in 1:length(mat$age.days)) {

	mat$zwfl[i]<-NA

       if(mat$oedema[i]!="y") {

		if( (!is.na(mat$age.days[i]) & mat$age.days[i]<731) | (is.na(mat$age.days[i]) & !is.na(mat$l.h[i]) & (mat$l.h[i]=="l" | mat$l.h[i]=="L")) | (is.na(mat$age.days[i]) & is.na(mat$l.h[i]) & !is.na(mat$clenhei[i]) & mat$clenhei[i]<87) ) {

			if(!is.na(mat$clenhei[i]) & mat$clenhei[i]>=45 & mat$clenhei[i]<=110) {

			### Interpolated l,m,s values

			low.len<-trunc(mat$clenhei[i]*10)/10
          upp.len<-trunc(mat$clenhei[i]*10+1)/10
			diff.len<-(mat$clenhei[i]-low.len)/0.1

			if(diff.len>0) {
			l.val<-wflanthro$l[wflanthro$length==low.len & wflanthro$sex==mat$sex[i]]+diff.len*( wflanthro$l[wflanthro$length==upp.len & wflanthro$sex==mat$sex[i]]-wflanthro$l[wflanthro$length==low.len & wflanthro$sex==mat$sex[i]] )
			m.val<-wflanthro$m[wflanthro$length==low.len & wflanthro$sex==mat$sex[i]]+diff.len*( wflanthro$m[wflanthro$length==upp.len & wflanthro$sex==mat$sex[i]]-wflanthro$m[wflanthro$length==low.len & wflanthro$sex==mat$sex[i]] )
			s.val<-wflanthro$s[wflanthro$length==low.len & wflanthro$sex==mat$sex[i]]+diff.len*( wflanthro$s[wflanthro$length==upp.len & wflanthro$sex==mat$sex[i]]-wflanthro$s[wflanthro$length==low.len & wflanthro$sex==mat$sex[i]] )
			} else {
				l.val<-wflanthro$l[wflanthro$length==low.len & wflanthro$sex==mat$sex[i]]
				m.val<-wflanthro$m[wflanthro$length==low.len & wflanthro$sex==mat$sex[i]]
				s.val<-wflanthro$s[wflanthro$length==low.len & wflanthro$sex==mat$sex[i]]
			}

			mat$zwfl[i]<-(((mat$weight[i]/m.val)^l.val)-1)/(s.val*l.val)
			if(!is.na(mat$zwfl[i]) & mat$zwfl[i]>3) {
							sd3pos<- m.val*((1+l.val*s.val*3)^(1/l.val))
							sd23pos<- sd3pos- m.val*((1+l.val*s.val*2)^(1/l.val))
							mat$zwfl[i]<- 3+((mat$weight[i]-sd3pos)/sd23pos)
						}
			if(!is.na(mat$zwfl[i]) & mat$zwfl[i]<(-3)) {
							sd3neg<- m.val*((1+l.val*s.val*(-3))**(1/l.val))
							sd23neg<- m.val*((1+l.val*s.val*(-2))**(1/l.val))-sd3neg
							mat$zwfl[i]<- (-3)-((sd3neg-mat$weight[i])/sd23neg)
							}
				}
			}

			else 		if( (!is.na(mat$age.days[i]) & mat$age.days[i]>=731) | (is.na(mat$age.days[i]) & !is.na(mat$l.h[i]) & (mat$l.h[i]=="h" | mat$l.h[i]=="H"))  | (is.na(mat$age.days[i]) & is.na(mat$l.h[i]) & !is.na(mat$clenhei[i]) & mat$clenhei[i]>=87) ) {

			if(!is.na(mat$clenhei[i]) & mat$clenhei[i]>=65 & mat$clenhei[i]<=120) {

			### Interpolated l,m,s values

			low.len<-trunc(mat$clenhei[i]*10)/10
          		upp.len<-trunc(mat$clenhei[i]*10+1)/10
			diff.len<-(mat$clenhei[i]-low.len)/0.1

			if(diff.len>0) {
			l.val<-wfhanthro$l[wfhanthro$height==low.len & wfhanthro$sex==mat$sex[i]]+diff.len*( wfhanthro$l[wfhanthro$height==upp.len & wfhanthro$sex==mat$sex[i]]-wfhanthro$l[wfhanthro$height==low.len & wfhanthro$sex==mat$sex[i]] )
			m.val<-wfhanthro$m[wfhanthro$height==low.len & wfhanthro$sex==mat$sex[i]]+diff.len*( wfhanthro$m[wfhanthro$height==upp.len & wfhanthro$sex==mat$sex[i]]-wfhanthro$m[wfhanthro$height==low.len & wfhanthro$sex==mat$sex[i]] )
			s.val<-wfhanthro$s[wfhanthro$height==low.len & wfhanthro$sex==mat$sex[i]]+diff.len*( wfhanthro$s[wfhanthro$height==upp.len & wfhanthro$sex==mat$sex[i]]-wfhanthro$s[wfhanthro$height==low.len & wfhanthro$sex==mat$sex[i]] )
          } else {
			l.val<-wfhanthro$l[wfhanthro$height==low.len & wfhanthro$sex==mat$sex[i]]
			m.val<-wfhanthro$m[wfhanthro$height==low.len & wfhanthro$sex==mat$sex[i]]
			s.val<-wfhanthro$s[wfhanthro$height==low.len & wfhanthro$sex==mat$sex[i]]
			}

			mat$zwfl[i]<-(((mat$weight[i]/m.val)^l.val)-1)/(s.val*l.val)
			if(!is.na(mat$zwfl[i]) & mat$zwfl[i]>3) {
							sd3pos<- m.val*((1+l.val*s.val*3)^(1/l.val))
							sd23pos<- sd3pos- m.val*((1+l.val*s.val*2)^(1/l.val))
							mat$zwfl[i]<- 3+((mat$weight[i]-sd3pos)/sd23pos)
							}
			if(!is.na(mat$zwfl[i]) & mat$zwfl[i]<(-3)) {
							sd3neg<- m.val*((1+l.val*s.val*(-3))**(1/l.val))
							sd23neg<- m.val*((1+l.val*s.val*(-2))**(1/l.val))-sd3neg
							mat$zwfl[i]<- (-3)-((sd3neg-mat$weight[i])/sd23neg)
							}
				}
			}
		}

		if(!is.na(mat$age.day[i]) & mat$age.days[i]>1856) mat$zwfl[i]<-NA

}

return(mat)
}

######################################################################################
### Function for calulating individual BMI-for-age z-scores
######################################################################################

calc.zbmi<-function(mat,bmianthro){

for(i in 1:length(mat$age.days)) {

	if(!is.na(mat$age.days[i]) & mat$oedema[i]!="y") {

		l.val<-bmianthro$l[bmianthro$age==mat$age.days[i] & bmianthro$sex==mat$sex[i]]
		m.val<-bmianthro$m[bmianthro$age==mat$age.days[i] & bmianthro$sex==mat$sex[i]]
		s.val<-bmianthro$s[bmianthro$age==mat$age.days[i] & bmianthro$sex==mat$sex[i]]

		mat$zbmi[i]<-(((mat$cbmi[i]/m.val)^l.val)-1)/(s.val*l.val)
		if(!is.na(mat$zbmi[i]) & mat$zbmi[i]>3) {
						sd3pos<- m.val*((1+l.val*s.val*3)^(1/l.val))
						sd23pos<- sd3pos- m.val*((1+l.val*s.val*2)^(1/l.val))
						mat$zbmi[i]<- 3+((mat$cbmi[i]-sd3pos)/sd23pos)
						}
		if(!is.na(mat$zbmi[i]) & mat$zbmi[i]< (-3)) {
						sd3neg<- m.val*((1+l.val*s.val*(-3))**(1/l.val))
						sd23neg<- m.val*((1+l.val*s.val*(-2))**(1/l.val))-sd3neg
						mat$zbmi[i]<- (-3)+((mat$cbmi[i]-sd3neg)/sd23neg)
						}

		} else mat$zbmi[i]<-NA

}

return(mat)
}

###################################################################################
#### Main function starts here: igrowup
###################################################################################

###############################################################################################################################################
#### This function can be used to:
#### 1. Calculate the z-scores for the indicators: length/height-for-age, weight-for-age, weight-for-legnth/height and body mass index-for-age
####    The output file with z-scores values is exported the file to an Excel spreadsheet (see readme file);
#### 2. Calculate the prevalence rates of stunting, underweight, wasting and overweight, and z-scores means and standard deviations. Results
####    are exported to an Excel spreadsheet, displayed by age group.
###############################################################################################################################################

#############################################################################
##### Function for calculating the z-scores for all indicators
#############################################################################

igrowup.standard <- function(FileLab="Temp",FilePath="C:\\Documents and Settings",mydf,sex,age,age.month=F,weight=rep(NA,dim(mydf)[1]),lenhei=rep(NA,dim(mydf)[1]),measure=rep(NA,dim(mydf)[1]),
           headc=rep(NA,dim(mydf)[1]),armc=rep(NA,dim(mydf)[1]),triskin=rep(NA,dim(mydf)[1]),subskin=rep(NA,dim(mydf)[1]),oedema=rep("n",dim(mydf)[1]),sw=rep(1,dim(mydf)[1])) {

#############################################################################
###########   Calculating the z-scores for all indicators
#############################################################################

   old <- options(warn=(-1))

   sex.x<-as.character(get(deparse(substitute(mydf)))[,deparse(substitute(sex))])
   age.x<-as.double(get(deparse(substitute(mydf)))[,deparse(substitute(age))])
   if(!missing(weight)) weight.x<-as.double(get(deparse(substitute(mydf)))[,deparse(substitute(weight))]) else weight.x<-as.double(weight)
   if(!missing(lenhei)) lenhei.x<-as.double(get(deparse(substitute(mydf)))[,deparse(substitute(lenhei))]) else lenhei.x<-as.double(lenhei)
   if(!missing(headc)) headc.x<-as.double(get(deparse(substitute(mydf)))[,deparse(substitute(headc))]) else headc.x<-as.double(headc)
   if(!missing(armc)) armc.x<-as.double(get(deparse(substitute(mydf)))[,deparse(substitute(armc))]) else armc.x<-as.double(armc)
   if(!missing(triskin)) triskin.x<-as.double(get(deparse(substitute(mydf)))[,deparse(substitute(triskin))]) else triskin.x<-as.double(triskin)
   if(!missing(subskin)) subskin.x<-as.double(get(deparse(substitute(mydf)))[,deparse(substitute(subskin))]) else subskin.x<-as.double(subskin)
   if(!missing(measure)) lorh.vec<-as.character(get(deparse(substitute(mydf)))[,deparse(substitute(measure))]) else lorh.vec<-as.character(measure)
   if(!missing(oedema)) oedema.vec<-as.character(get(deparse(substitute(mydf)))[,deparse(substitute(oedema))]) else oedema.vec<-oedema
   if(!missing(sw))	sw<-as.double(get(deparse(substitute(mydf)))[,deparse(substitute(sw))])	else sw<-as.double(sw)
   sw<-ifelse(is.na(sw),0,sw)

	sex.vec<-NULL

	if(age.month) age.vec<-rounde(age.x*30.4375) else age.vec<-rounde(age.x)
	lenhei.vec<-ifelse((!is.na(age.vec) & age.vec<731 & !is.na(lorh.vec) & (lorh.vec=="h" | lorh.vec=="H")),lenhei.x+0.7,#
		  ifelse((!is.na(age.vec) & age.vec>=731 & !is.na(lorh.vec) & (lorh.vec=="l" | lorh.vec=="L")),lenhei.x-0.7,lenhei.x))

   sex.vec<-ifelse(!is.na(sex.x) & (sex.x=="m" | sex.x=="M" | sex.x=="1"),1,ifelse(!is.na(sex.x) & (sex.x=="f" | sex.x=="F" | sex.x=="2"),2,NA))

   lorh.vec<-ifelse(is.na(lorh.vec) | lorh.vec=="l" | lorh.vec=="L" | lorh.vec=="h" | lorh.vec=="H",lorh.vec,NA)

   oedema.vec<-ifelse(oedema.vec=="n" | oedema.vec=="N","n",ifelse(oedema.vec=="y" | oedema.vec=="Y","y","n"))

   mat<-cbind.data.frame(age.x,as.integer(age.vec),as.double(sex.vec),weight.x,lenhei.x,lorh.vec,lenhei.vec,headc.x,armc.x,triskin.x,subskin.x,oedema.vec,sw,stringsAsFactors=F)
	names(mat)<-c("age","age.days","sex","weight","len.hei","l.h","clenhei","headc","armc","triskin","subskin","oedema","sw")

	mat$cbmi<-mat$weight/((lenhei.vec/100)^2)
	mat$zlen<-rep(NA,length(mat$age))
	mat$zwei<-rep(NA,length(mat$age))
	mat$zwfl<-rep(NA,length(mat$age))
	mat$zbmi<-rep(NA,length(mat$age))
	mat$zhc<-rep(NA,length(mat$age))
	mat$zac<-rep(NA,length(mat$age))
	mat$zts<-rep(NA,length(mat$age))
	mat$zss<-rep(NA,length(mat$age))

	mat$zlen<-rep(NA,length(mat$age))
	mat$flen<-rep(NA,length(mat$age))
	mat$fwei<-rep(NA,length(mat$age))
	mat$fwfl<-rep(NA,length(mat$age))
	mat$fbmi<-rep(NA,length(mat$age))
	mat$fhc<-rep(NA,length(mat$age))
	mat$fac<-rep(NA,length(mat$age))
	mat$fts<-rep(NA,length(mat$age))
	mat$fss<-rep(NA,length(mat$age))

#############################################################################
###########   Calculating the z-scores for all indicators
#############################################################################

cat("Please wait while calculating z-scores...\n")

### Length-for-age z-score

mat<-calc.zlen(mat,lenanthro)

### Head circumference-for-age z-score

mat<-calc.zhc(mat,hcanthro)

### Weight-for-age z-score

mat<-calc.zwei(mat,weianthro)

### Arm circumference-for-age z-score

mat<-calc.zac(mat,acanthro)

### Triceps skinfold-for-age z-score

mat<-calc.zts(mat,tsanthro)

### Subscapular skinfold-for-age z-score

mat<-calc.zss(mat,ssanthro)

### Weight-for-length/height z-score

mat<-calc.zwfl(mat,wflanthro,wfhanthro)

### BMI-for-age z-score

mat<-calc.zbmi(mat,bmianthro)

#### Rounding the z-scores to two decimals

			mat$zlen<-rounde(mat$zlen,digits=2)
			mat$zwei<-rounde(mat$zwei,digits=2)
			mat$zwfl<-rounde(mat$zwfl,digits=2)
			mat$zbmi<-rounde(mat$zbmi,digits=2)
			mat$zhc<-rounde(mat$zhc,digits=2)
			mat$zac<-rounde(mat$zac,digits=2)
			mat$zts<-rounde(mat$zts,digits=2)
			mat$zss<-rounde(mat$zss,digits=2)

#### Flagging z-score values for individual indicators

			mat$flen<-ifelse(abs(mat$zlen) > 6,1,0)
			mat$fwei<-ifelse(mat$zwei > 5 | mat$zwei < (-6),1,0)
			mat$fwfl<-ifelse(abs(mat$zwfl) > 5,1,0)
			mat$fbmi<-ifelse(abs(mat$zbmi) > 5,1,0)
			mat$fhc<-ifelse(abs(mat$zhc) > 5,1,0)
			mat$fac<-ifelse(abs(mat$zac) > 5,1,0)
			mat$fts<-ifelse(abs(mat$zts) > 5,1,0)
			mat$fss<-ifelse(abs(mat$zss) > 5,1,0)

cat(paste("Z-scores calculated - preparing matrix to be exported..."))

mat<-cbind.data.frame(mydf,mat[,-c(1,3:6,8:9)])

###################################################################################################
######### Export data frame with z-scores and flag variables
###################################################################################################

assign("matz",mat,envir = .GlobalEnv)

write.table(matz, file=paste(FilePath,"\\",FileLab,"_z_st.csv",sep=""),na="",row.names = FALSE,sep=",",quote = TRUE)

cat(paste("Z-scores calculated and exported to ",FilePath,"\\",FileLab,"_z_st.csv\n\n",sep=""))

#######################################################################################################
#### Calculating prevalences and summary statistics.
#######################################################################################################

if(any(sw <0)) stop("Negative weights are not allowed and program will stop. Prevalence tables will not be produced.")

mat.out<-mat

################################
#### Creating age group variable
################################

mat.out$sw.vec<-sw
mat.out$sex.vec<-as.double(sex.vec)
mat.out$oedema.vec<-as.character(oedema.vec)

if(age.month) mat.out$agegr <- ifelse(!is.na(age.x) & age.x<6,0,ifelse(!is.na(age.x) & age.x<12,6,#
                     ifelse(!is.na(age.x) & age.x<24,12,ifelse(!is.na(age.x) & age.x<36,24,#
                     ifelse(!is.na(age.x) & age.x<48,36,ifelse(!is.na(age.x) & age.x<61,48,NA)  )))))

else mat.out$agegr <- ifelse(!is.na(mat.out$age.days) & mat.out$age.days/30.4375<6,0,ifelse(!is.na(mat.out$age.days) & mat.out$age.days/30.4375<12,6,#
                     ifelse(!is.na(mat.out$age.days) & mat.out$age.days/30.4375<24,12,ifelse(!is.na(mat.out$age.days) & mat.out$age.days/30.4375<36,24,#
                     ifelse(!is.na(mat.out$age.days) & mat.out$age.days/30.4375<48,36,ifelse(!is.na(mat.out$age.days) & mat.out$age.days/30.4375<61,48,NA)  )))))

##############################################
#### Make z-score as missing if it is flagged
##############################################

mat.out$zlen<-ifelse(!is.na(mat.out$flen) & mat.out$flen!=0,NA,mat.out$zlen)
mat.out$zwei<-ifelse(!is.na(mat.out$fwei) & mat.out$fwei!=0,NA,mat.out$zwei)
mat.out$zwfl<-ifelse(!is.na(mat.out$fwfl) & mat.out$fwfl!=0,NA,mat.out$zwfl)
mat.out$zbmi<-ifelse(!is.na(mat.out$fbmi) & mat.out$fbmi!=0,NA,mat.out$zbmi)
mat.out$zhc<-ifelse(!is.na(mat.out$fhc) & mat.out$fhc!=0,NA,mat.out$zhc)
mat.out$zac<-ifelse(!is.na(mat.out$fac) & mat.out$fac!=0,NA,mat.out$zac)
mat.out$zts<-ifelse(!is.na(mat.out$fts) & mat.out$fts!=0,NA,mat.out$zts)
mat.out$zss<-ifelse(!is.na(mat.out$fss) & mat.out$fss!=0,NA,mat.out$zss)

##############################################
#### Include all levels of age group variable
##############################################

mat.aux<-as.data.frame(cbind(array(rep(NA,((dim(mat.out)[2]-1)*6)),dim=c(6,(dim(mat.out)[2]-1)) ),c(0,6,12,24,36,48)))
names(mat.aux)<-names(mat.out)
mat.out<-rbind(mat.out,mat.aux)

##############################################################################################
#### Make Oedema variable to be "n" if age greater than 60 completed months (>=61 months).
#### This is beacuse children with oedema counts in the prevalence even if z-score is missing
#### for weight related indicators.
##############################################################################################

mat.out$oedema.vec<-ifelse((!is.na(mat.out$age.days) & mat.out$age.days/30.4375>=61) | mat.out$oedema.vec=="NA","n",mat.out$oedema.vec)

#####################################################################################################################################################
#### Creating matrix with estimated prevalences, confidence intervals, and means and standard deviations of z-scores and exporting it to Excel file.
#####################################################################################################################################################

cat("\nPlease wait while calculating prevalences and z-score summary statistics...\n")

#### Sexes combined

#### % < -3 SD for all the indicators
mat<-t(cbind.data.frame(#
       prevnh(-3,mat.out$zwei,mat.out$sw.vec,mat.out$oedema.vec),lapply(split(mat.out, mat.out$agegr),function(z) prevnh(-3, z$zwei, z$sw.vec, z$oedema.vec)),#
       prevnh.L(-3,mat.out$zlen,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevnh.L(-3, z$zlen, z$sw.vec)),#
       prevnh(-3,mat.out$zwfl,mat.out$sw.vec,mat.out$oedema.vec),lapply(split(mat.out, mat.out$agegr),function(z) prevnh(-3, z$zwfl, z$sw.vec, z$oedema.vec)),#
       prevnh(-3,mat.out$zbmi,mat.out$sw.vec,mat.out$oedema.vec),lapply(split(mat.out, mat.out$agegr),function(z) prevnh(-3, z$zbmi, z$sw.vec, z$oedema.vec))))

#### % < -2 SD for all the indicators
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       prevnh(-2,mat.out$zwei,mat.out$sw.vec,mat.out$oedema.vec),lapply(split(mat.out, mat.out$agegr),function(z) prevnh(-2, z$zwei, z$sw.vec, z$oedema.vec)),#
       prevnh.L(-2,mat.out$zlen,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevnh.L(-2, z$zlen, z$sw.vec)),#
       prevnh(-2,mat.out$zwfl,mat.out$sw.vec,mat.out$oedema.vec),lapply(split(mat.out, mat.out$agegr),function(z) prevnh(-2, z$zwfl, z$sw.vec, z$oedema.vec)),#
       prevnh(-2,mat.out$zbmi,mat.out$sw.vec,mat.out$oedema.vec),lapply(split(mat.out, mat.out$agegr),function(z) prevnh(-2, z$zbmi, z$sw.vec, z$oedema.vec))))[,-1])

#### % > +1 SD for weight-for-length/height and bmi-for-age
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       array(rep(NA,28),dim=c(4,7)),#
       array(rep(NA,28),dim=c(4,7)),#
       prevph(1,mat.out$zwfl,mat.out$sw.vec,mat.out$oedema.vec),lapply(split(mat.out, mat.out$agegr),function(z) prevph(1, z$zwfl, z$sw.vec, z$oedema.vec)),#
       prevph(1,mat.out$zbmi,mat.out$sw.vec,mat.out$oedema.vec),lapply(split(mat.out, mat.out$agegr),function(z) prevph(1, z$zbmi, z$sw.vec, z$oedema.vec))))[,-1])

#### % > +2 SD for weight-for-length/height and bmi-for-age
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       array(rep(NA,28),dim=c(4,7)),#
       array(rep(NA,28),dim=c(4,7)),#
       prevph(2,mat.out$zwfl,mat.out$sw.vec,mat.out$oedema.vec),lapply(split(mat.out, mat.out$agegr),function(z) prevph(2, z$zwfl, z$sw.vec, z$oedema.vec)),#
       prevph(2,mat.out$zbmi,mat.out$sw.vec,mat.out$oedema.vec),lapply(split(mat.out, mat.out$agegr),function(z) prevph(2, z$zbmi, z$sw.vec, z$oedema.vec))))[,-1])

#### % > +3 SD for weight-for-length/height and bmi-for-age
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       array(rep(NA,28),dim=c(4,7)),#
       array(rep(NA,28),dim=c(4,7)),#
       prevph(3,mat.out$zwfl,mat.out$sw.vec,mat.out$oedema.vec),lapply(split(mat.out, mat.out$agegr),function(z) prevph(3, z$zwfl, z$sw.vec, z$oedema.vec)),#
       prevph(3,mat.out$zbmi,mat.out$sw.vec,mat.out$oedema.vec),lapply(split(mat.out, mat.out$agegr),function(z) prevph(3, z$zbmi, z$sw.vec, z$oedema.vec))))[,-1])

#### Means of z-scores for all the indicators
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       wmean(mat.out$zwei,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wmean(z$zwei,z$sw.vec)),#
       wmean(mat.out$zlen,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wmean(z$zlen,z$sw.vec)),#
       wmean(mat.out$zwfl,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wmean(z$zwfl,z$sw.vec)),#
       wmean(mat.out$zbmi,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wmean(z$zbmi,z$sw.vec)))))

#### Standard deviations of z-scores for all the indicators
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       wsd(mat.out$zwei,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wsd(z$zwei,z$sw.vec)),#
       wsd(mat.out$zlen,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wsd(z$zlen,z$sw.vec)),#
       wsd(mat.out$zwfl,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wsd(z$zwfl,z$sw.vec)),#
       wsd(mat.out$zbmi,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wsd(z$zbmi,z$sw.vec)))))

####################################################################################################################
##### Creating matrix to export as Excel file

mat[1:14,8]<-mat[1:14,17]
mat[1:14,9]<-mat[1:14,18]
mat[1:14,10:18]<-array(rep("",126),dim=c(14,9))
rm(mat1)
mat1<-rbind(c("Set 1:","Sexes","combined",rep("",15)),c("Weight","-for-","age",rep("",15)),#
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","Mean","SD","","", "","","", "","","", ""),mat[1:7,],#
                       c("Length","/height","-for-","age",rep("",14)),
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","Mean","SD","","", "","","", "","","", ""),mat[8:14,],#
                       c("Weight","-for-","length","/height",rep("",14)),
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","% > +1 SD","95%", "C.I.","% > +2 SD","95%", "C.I.","% > +3 SD","95%", "C.I.","Mean","SD"),mat[15:21,],#
                       c("BMI","-for-","age",rep("",15)),
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","% > +1 SD","95%", "C.I.","% > +2 SD","95%", "C.I.","% > +3 SD","95%", "C.I.","Mean","SD"),mat[22:28,])

for(j in 1:dim(mat1)[2]) mat1[,j]<-ifelse(mat1[,j]=="NA" | mat1[,j]=="NaN","",mat1[,j])

mat1<-cbind(c("",rep(c(""," Age"," 0-60","0-5"," 6-11"," 12-23"," 24-35"," 36-47"," 48-60"),4)),mat1)

####################################################################################################################

##### For boys and girls

for(i in 1:2) {

mat.out.sex<-mat.out[!is.na(mat.out$sex.vec) & mat.out$sex.vec==i,]

mat.aux<-as.data.frame(cbind(array(rep(NA,((dim(mat.out.sex)[2]-1)*6)),dim=c(6,(dim(mat.out.sex)[2]-1)) ),c(0,6,12,24,36,48)))
names(mat.aux)<-names(mat.out.sex)
mat.out.sex<-rbind.data.frame(mat.out.sex,mat.aux )
mat.out.sex$oedema.vec<-ifelse((!is.na(mat.out.sex$age.days) & mat.out.sex$age.days/30.4375>=61) | mat.out.sex$oedema.vec=="NA","n",mat.out.sex$oedema.vec)

#### % < -3 SD for all the indicators
mat<-t(cbind.data.frame(#
       prevnh(-3,mat.out.sex$zwei,mat.out.sex$sw.vec,mat.out.sex$oedema.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) prevnh(-3, z$zwei, z$sw.vec, z$oedema.vec)),#
       prevnh.L(-3,mat.out.sex$zlen,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevnh.L(-3, z$zlen, z$sw.vec)),#
       prevnh(-3,mat.out.sex$zwfl,mat.out.sex$sw.vec,mat.out.sex$oedema.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) prevnh(-3, z$zwfl, z$sw.vec, z$oedema.vec)),#
       prevnh(-3,mat.out.sex$zbmi,mat.out.sex$sw.vec,mat.out.sex$oedema.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) prevnh(-3, z$zbmi, z$sw.vec, z$oedema.vec))))

#### % < -2 SD for all the indicators
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       prevnh(-2,mat.out.sex$zwei,mat.out.sex$sw.vec,mat.out.sex$oedema.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) prevnh(-2, z$zwei, z$sw.vec, z$oedema.vec)),#
       prevnh.L(-2,mat.out.sex$zlen,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevnh.L(-2, z$zlen, z$sw.vec)),#
       prevnh(-2,mat.out.sex$zwfl,mat.out.sex$sw.vec,mat.out.sex$oedema.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) prevnh(-2, z$zwfl, z$sw.vec, z$oedema.vec)),#
       prevnh(-2,mat.out.sex$zbmi,mat.out.sex$sw.vec,mat.out.sex$oedema.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) prevnh(-2, z$zbmi, z$sw.vec, z$oedema.vec))))[,-1])

#### % > +1 SD for weight-for-length/height and bmi-for-age
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       array(rep(NA,28),dim=c(4,7)),#
       array(rep(NA,28),dim=c(4,7)),#
       prevph(1,mat.out.sex$zwfl,mat.out.sex$sw.vec,mat.out.sex$oedema.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) prevph(1, z$zwfl, z$sw.vec, z$oedema.vec)),#
       prevph(1,mat.out.sex$zbmi,mat.out.sex$sw.vec,mat.out.sex$oedema.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) prevph(1, z$zbmi, z$sw.vec, z$oedema.vec))))[,-1])

#### % > +2 SD for weight-for-length/height and bmi-for-age
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       array(rep(NA,28),dim=c(4,7)),#
       array(rep(NA,28),dim=c(4,7)),#
       prevph(2,mat.out.sex$zwfl,mat.out.sex$sw.vec,mat.out.sex$oedema.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) prevph(2, z$zwfl, z$sw.vec, z$oedema.vec)),#
       prevph(2,mat.out.sex$zbmi,mat.out.sex$sw.vec,mat.out.sex$oedema.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) prevph(2, z$zbmi, z$sw.vec, z$oedema.vec))))[,-1])

#### % > +3 SD for weight-for-length/height and bmi-for-age
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       array(rep(NA,28),dim=c(4,7)),#
       array(rep(NA,28),dim=c(4,7)),#
       prevph(3,mat.out.sex$zwfl,mat.out.sex$sw.vec,mat.out.sex$oedema.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) prevph(3, z$zwfl, z$sw.vec, z$oedema.vec)),#
       prevph(3,mat.out.sex$zbmi,mat.out.sex$sw.vec,mat.out.sex$oedema.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) prevph(3, z$zbmi, z$sw.vec, z$oedema.vec))))[,-1])

#### Means of z-scores for all the indicators
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       wmean(mat.out.sex$zwei,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wmean(z$zwei,z$sw.vec)),#
       wmean(mat.out.sex$zlen,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wmean(z$zlen,z$sw.vec)),#
       wmean(mat.out.sex$zwfl,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wmean(z$zwfl,z$sw.vec)),#
       wmean(mat.out.sex$zbmi,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wmean(z$zbmi,z$sw.vec)))))

#### Standard deviations of z-scores for all the indicators
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       wsd(mat.out.sex$zwei,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wsd(z$zwei,z$sw.vec)),#
       wsd(mat.out.sex$zlen,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wsd(z$zlen,z$sw.vec)),#
       wsd(mat.out.sex$zwfl,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wsd(z$zwfl,z$sw.vec)),#
       wsd(mat.out.sex$zbmi,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wsd(z$zbmi,z$sw.vec)))))

####################################################################################################################
##### Creating matrix to export as Excel file

mat[1:14,8]<-mat[1:14,17]
mat[1:14,9]<-mat[1:14,18]
mat[1:14,10:18]<-array(rep("",126),dim=c(14,9))

mat2<-rbind(c(paste("Set ",i+1,":",sep=""),c("Males","Females")[i],rep("",16)),c("Weight","-for-","age",rep("",15)),#
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","Mean","SD","","", "","","", "","","", ""),mat[1:7,],#
                       c("Length","/height","-for-","age",rep("",14)),
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","Mean","SD","","", "","","", "","","", ""),mat[8:14,],#
                       c("Weight","-for-","length","/height",rep("",14)),
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","% > +1 SD","95%", "C.I.","% > +2 SD","95%", "C.I.","% > +3 SD","95%", "C.I.","Mean","SD"),mat[15:21,],#
                       c("BMI","-for-","age",rep("",15)),
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","% > +1 SD","95%", "C.I.","% > +2 SD","95%", "C.I.","% > +3 SD","95%", "C.I.","Mean","SD"),mat[22:28,])

for(j in 1:dim(mat2)[2]) mat2[,j]<-ifelse(mat2[,j]=="NA" | mat2[,j]=="NaN","",mat2[,j])

mat2<-cbind(c("",rep(c(""," Age"," 0-60"," 0-5"," 6-11"," 12-23"," 24-35"," 36-47"," 48-60"),4)),mat2)

names(mat2)<-names(mat1)

mat1<-rbind(mat1,mat2)

}    #### End of loop for sex

###################################################################################################################
######### Creating another matrix for the second set of indicators
###################################################################################################################

#####################################################################################################################################################
#### Creating matrix with estimated prevalences, confidence intervals, and means and standard deviations of z-scores and exporting it to Excel file.
#####################################################################################################################################################

#### Sexes combined

#### % < -3 SD for all the indicators
mat<-t(cbind.data.frame(#
       prevnh.L(-3,mat.out$zhc,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevnh.L(-3, z$zhc, z$sw.vec)),#
       prevnh.L(-3,mat.out$zac,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevnh.L(-3, z$zac, z$sw.vec)),#
       prevnh.L(-3,mat.out$zts,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevnh.L(-3, z$zts, z$sw.vec)),#
       prevnh.L(-3,mat.out$zss,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevnh.L(-3, z$zss, z$sw.vec))))

#### % < -2 SD for all the indicators
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       prevnh.L(-2,mat.out$zhc,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevnh.L(-2, z$zhc, z$sw.vec)),#
       prevnh.L(-2,mat.out$zac,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevnh.L(-2, z$zac, z$sw.vec)),#
       prevnh.L(-2,mat.out$zts,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevnh.L(-2, z$zts, z$sw.vec)),#
       prevnh.L(-2,mat.out$zss,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevnh.L(-2, z$zss, z$sw.vec))))[,-1])

#### % > +1 SD for weight-for-length/height and bmi-for-age
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       prevph.L(1,mat.out$zhc,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevph.L(1, z$zhc, z$sw.vec)),#
       prevph.L(1,mat.out$zac,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevph.L(1, z$zac, z$sw.vec)),#
       prevph.L(1,mat.out$zts,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevph.L(1, z$zts, z$sw.vec)),#
       prevph.L(1,mat.out$zss,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevph.L(1, z$zss, z$sw.vec))))[,-1])

#### % > +2 SD for weight-for-length/height and bmi-for-age
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       prevph.L(2,mat.out$zhc,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevph.L(2, z$zhc, z$sw.vec)),#
       prevph.L(2,mat.out$zac,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevph.L(2, z$zac, z$sw.vec)),#
       prevph.L(2,mat.out$zts,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevph.L(2, z$zts, z$sw.vec)),#
       prevph.L(2,mat.out$zss,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevph.L(2, z$zss, z$sw.vec))))[,-1])

#### % > +3 SD for weight-for-length/height and bmi-for-age
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       prevph.L(3,mat.out$zhc,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevph.L(3, z$zhc, z$sw.vec)),#
       prevph.L(3,mat.out$zac,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevph.L(3, z$zac, z$sw.vec)),#
       prevph.L(3,mat.out$zts,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevph.L(3, z$zts, z$sw.vec)),#
       prevph.L(3,mat.out$zss,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr), function(z) prevph.L(3, z$zss, z$sw.vec))))[,-1])

#### Means of z-scores for all the indicators
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       wmean(mat.out$zhc,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wmean(z$zhc,z$sw.vec)),#
       wmean(mat.out$zac,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wmean(z$zac,z$sw.vec)),#
       wmean(mat.out$zts,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wmean(z$zts,z$sw.vec)),#
       wmean(mat.out$zss,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wmean(z$zss,z$sw.vec)))))

#### Standard deviations of z-scores for all the indicators
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       wsd(mat.out$zhc,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wsd(z$zhc,z$sw.vec)),#
       wsd(mat.out$zac,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wsd(z$zac,z$sw.vec)),#
       wsd(mat.out$zts,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wsd(z$zts,z$sw.vec)),#
       wsd(mat.out$zss,mat.out$sw.vec),lapply(split(mat.out, mat.out$agegr),function(z) wsd(z$zss,z$sw.vec)))))

####################################################################################################################
##### Exporting matrix to Excel file

mat3<-rbind(c("Set 1:","Sexes","combined",rep("",15)),c("Head ","circumference","-for-","age",rep("",14)),#
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","% > +1 SD","95%", "C.I.","% > +2 SD","95%", "C.I.","% > +3 SD","95%", "C.I.","Mean","SD"),mat[1:7,],#
                       c("MUAC","-for-","age","",rep("",14)),
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","% > +1 SD","95%", "C.I.","% > +2 SD","95%", "C.I.","% > +3 SD","95%", "C.I.","Mean","SD"),mat[8:14,],#
                       c("Triceps ","skinfold","-for-","age",rep("",14)),
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","% > +1 SD","95%", "C.I.","% > +2 SD","95%", "C.I.","% > +3 SD","95%", "C.I.","Mean","SD"),mat[15:21,],#
                       c("Subscapular ","skinfold","-for-","age",rep("",14)),
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","% > +1 SD","95%", "C.I.","% > +2 SD","95%", "C.I.","% > +3 SD","95%", "C.I.","Mean","SD"),mat[22:28,])

for(j in 1:dim(mat3)[2]) mat3[,j]<-ifelse(mat3[,j]=="NA" | mat3[,j]=="NaN","",mat3[,j])

mat3<-cbind.data.frame(c("",c(c(""," Age"," 0-60"," 0-5"," 6-11"," 12-23"," 24-35"," 36-47"," 48-60"),rep(c(""," Age"," 3-60"," 3-5"," 6-11"," 12-23"," 24-35"," 36-47"," 48-60"),3))),mat3)

####################################################################################################################

##### For boys and girls

for(i in 1:2) {

mat.out.sex<-mat.out[!is.na(mat.out$sex.vec) & mat.out$sex.vec==i,]
mat.aux<- as.data.frame(cbind(array(rep(NA,((dim(mat.out.sex)[2]-1)*6)),dim=c(6,(dim(mat.out.sex)[2]-1)) ),c(0,6,12,24,36,48))	)
names(mat.aux)<-names(mat.out.sex)
mat.out.sex<-rbind(mat.out.sex, mat.aux)
mat.out.sex$oedema.vec<-ifelse((!is.na(mat.out.sex$age.days) & mat.out.sex$age.days/30.4375>=61) | mat.out.sex$oedema.vec=="NA","n",mat.out.sex$oedema.vec)

#### % < -3 SD for all the indicators
mat<-t(cbind.data.frame(#
       prevnh.L(-3,mat.out.sex$zhc,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevnh.L(-3, z$zhc, z$sw.vec)),#
       prevnh.L(-3,mat.out.sex$zac,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevnh.L(-3, z$zac, z$sw.vec)),#
       prevnh.L(-3,mat.out.sex$zts,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevnh.L(-3, z$zts, z$sw.vec)),#
       prevnh.L(-3,mat.out.sex$zss,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevnh.L(-3, z$zss, z$sw.vec))))

#### % < -2 SD for all the indicators
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       prevnh.L(-2,mat.out.sex$zhc,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevnh.L(-2, z$zhc, z$sw.vec)),#
       prevnh.L(-2,mat.out.sex$zac,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevnh.L(-2, z$zac, z$sw.vec)),#
       prevnh.L(-2,mat.out.sex$zts,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevnh.L(-2, z$zts, z$sw.vec)),#
       prevnh.L(-2,mat.out.sex$zss,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevnh.L(-2, z$zss, z$sw.vec))))[,-1])

#### % > +1 SD for weight-for-length/height and bmi-for-age
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       prevph.L(1,mat.out.sex$zhc,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevph.L(1, z$zhc, z$sw.vec)),#
       prevph.L(1,mat.out.sex$zac,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevph.L(1, z$zac, z$sw.vec)),#
       prevph.L(1,mat.out.sex$zts,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevph.L(1, z$zts, z$sw.vec)),#
       prevph.L(1,mat.out.sex$zss,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevph.L(1, z$zss, z$sw.vec))))[,-1])

#### % > +2 SD for weight-for-length/height and bmi-for-age
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       prevph.L(2,mat.out.sex$zhc,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevph.L(2, z$zhc, z$sw.vec)),#
       prevph.L(2,mat.out.sex$zac,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevph.L(2, z$zac, z$sw.vec)),#
       prevph.L(2,mat.out.sex$zts,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevph.L(2, z$zts, z$sw.vec)),#
       prevph.L(2,mat.out.sex$zss,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevph.L(2, z$zss, z$sw.vec))))[,-1])

#### % > +3 SD for weight-for-length/height and bmi-for-age
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       prevph.L(3,mat.out.sex$zhc,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevph.L(3, z$zhc, z$sw.vec)),#
       prevph.L(3,mat.out.sex$zac,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevph.L(3, z$zac, z$sw.vec)),#
       prevph.L(3,mat.out.sex$zts,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevph.L(3, z$zts, z$sw.vec)),#
       prevph.L(3,mat.out.sex$zss,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr), function(z) prevph.L(3, z$zss, z$sw.vec))))[,-1])

#### Means of z-scores for all the indicators
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       wmean(mat.out.sex$zhc,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wmean(z$zhc,z$sw.vec)),#
       wmean(mat.out.sex$zac,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wmean(z$zac,z$sw.vec)),#
       wmean(mat.out.sex$zts,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wmean(z$zts,z$sw.vec)),#
       wmean(mat.out.sex$zss,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wmean(z$zss,z$sw.vec)))))

#### Standard deviations of z-scores for all the indicators
mat<-cbind.data.frame(mat,t(cbind.data.frame(#
       wsd(mat.out.sex$zhc,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wsd(z$zhc,z$sw.vec)),#
       wsd(mat.out.sex$zac,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wsd(z$zac,z$sw.vec)),#
       wsd(mat.out.sex$zts,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wsd(z$zts,z$sw.vec)),#
       wsd(mat.out.sex$zss,mat.out.sex$sw.vec),lapply(split(mat.out.sex, mat.out.sex$agegr),function(z) wsd(z$zss,z$sw.vec)))))

####################################################################################################################
##### Exporting matrix to Excel file

mat4<-rbind.data.frame(c(paste("Set ",i+1,":",sep=""),c("Males","Females")[i],rep("",16)),c("Head ","circumference","-for-","age",rep("",14)),#
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","% > +1 SD","95%", "C.I.","% > +2 SD","95%", "C.I.","% > +3 SD","95%", "C.I.","Mean","SD"),mat[1:7,],#
                       c("MUAC","-for-","age","",rep("",14)),
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","% > +1 SD","95%", "C.I.","% > +2 SD","95%", "C.I.","% > +3 SD","95%", "C.I.","Mean","SD"),mat[8:14,],#
                       c("Triceps ","skinfold","-for-","age",rep("",14)),
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","% > +1 SD","95%", "C.I.","% > +2 SD","95%", "C.I.","% > +3 SD","95%", "C.I.","Mean","SD"),mat[15:21,],#
                       c("Subscapular ","skinfold","-for-","age",rep("",14)),
                       c("N","% < -3 SD","95%", "C.I.","% < -2 SD","95%", "C.I.","% > +1 SD","95%", "C.I.","% > +2 SD","95%", "C.I.","% > +3 SD","95%", "C.I.","Mean","SD"),mat[22:28,])

for(j in 1:dim(mat4)[2]) mat4[,j]<-ifelse(mat4[,j]=="NA" | mat4[,j]=="NaN","",mat4[,j])

mat4<-cbind.data.frame(c("",c(c(""," Age"," 0-60"," 0-5"," 6-11"," 12-23"," 24-35"," 36-47"," 48-60"),rep(c(""," Age"," 3-60"," 3-5"," 6-11"," 12-23"," 24-35"," 36-47"," 48-60"),3))),mat4)

names(mat4)<-names(mat3)
mat3<-rbind.data.frame(mat3,mat4)

}    #### End of loop for sex

names(mat3)<-names(mat1)

mat3<-rbind.data.frame(mat1,mat3)

###################################################################################################################
######### Export table with prevalence values and their confidence intervals, and mean and SD of the z-scores
###################################################################################################################

assign("matprev",mat3,envir = .GlobalEnv)

write.table(matprev, file=paste(FilePath,"\\",FileLab,"_prev_st.csv",sep=""),na=" ",row.names = FALSE,col.names=F,sep=",",quote = TRUE)

cat(paste("Prevalences and z-score summary statistics calculated and exported to ",FilePath,"\\",FileLab,"_prev_st.csv\n",sep=""))

on.exit(options(old))

invisible()

}   #### End of function igrowup.standard


# load packages
library(dplyr)
library(tidyr)
library(ggplot2)
library(mirt)
library(readxl)

# Function for DIF Extraction
get.dif.items <- function(out.list,p.val,parms){
  dif.items <- NULL
  non.dif.items <- NULL
  for(i in 1:length(out.list)){ # loop list of items
    chi.sq <- out.list[[i]][2,6] #2 groups, so second row, and 6th column
    df <- out.list[[i]][2,7]
    p <- out.list[[i]][2,8]
    i.name <- names(out.list[i])
    d <- c(i.name,chi.sq,df,p,parms[i,])

    if(p < p.val){
      dif.items <- rbind(dif.items,d)
    }else{
      non.dif.items <- rbind(non.dif.items,d)
    }
  }
  if (!is.null(dif.items)) {
    dif.items <- data.frame(dif.items, row.names = NULL)
    colnames(dif.items)[1] <- "item"
    colnames(dif.items)[2] <- "chi.sq"
    colnames(dif.items)[3] <- "df"
    colnames(dif.items)[4] <- "p"

  }
  if (!is.null(non.dif.items)) {
    non.dif.items <- data.frame(non.dif.items, row.names = NULL)
    colnames(non.dif.items)[1] <- "item"
    colnames(non.dif.items)[2] <- "chi.sq"
    colnames(non.dif.items)[3] <- "df"
    colnames(non.dif.items)[4] <- "p"
  }
  r.list <- list(dif_items = dif.items, no_dif = non.dif.items)
  return(r.list)
}

# load data
belin <- read_excel('Data/IExcel_IRT_All5A.xlsx')

# Items names (column names of items)
english_items <- dplyr::select(belin, starts_with('Eng_AV_'))
math_items <- dplyr::select(belin, starts_with('Math_AV_'))
read_items <- dplyr::select(belin, starts_with('Read_AV_'))
sci_items <- dplyr::select(belin, starts_with("Sci_AV_"))

# group variable
grade <- as.character(belin$Grade)

# Eigenvalue
english_eigen <- eigen(cor(english_items))$values
english_eigen[1] / english_eigen[2]
english_eigen[1] / sum(english_eigen)

math_eigen <- eigen(cor(math_items))$values
math_eigen[1] / math_eigen[2]
math_eigen[1] / sum(math_eigen)

read_eigen <- eigen(cor(read_items))$values
read_eigen[1] / read_eigen[2]
read_eigen[1] / sum(read_eigen)

sci_eigen <- eigen(cor(sci_items))$values
sci_eigen[1] / sci_eigen[2]
sci_eigen[1] / sum(sci_eigen)

# CTT DIF ----
library(difR)

belin_mh <- cbind(math_items, select(belin, Grade))
names = c('5', '6')
difGMH(belin_mh, group = "Grade", focal.name = names,
       p.adjust.method = "BH")

difGenLogistic(belin_mh, group = "Grade", focal.name = names,
               p.adjust.method = "BH")
difGenLogistic(belin_mh, group = "Grade", focal.name = names,
               p.adjust.method = "BH", type = 'nudif')
difGenLogistic(belin_mh, group = "Grade", focal.name = names,
               p.adjust.method = "BH", type = 'udif')

# logistic regression ---
belin_mh <- belin_mh %>%
  mutate(total_score = rowSums(select(., starts_with("Math_AV_"))))

math_it2_log <- glm(Math_AV_2 ~ 1 + total_score + factor(Grade) + total_score:factor(Grade),
    data = belin_mh, family = binomial)
summary(math_it2_log)

#--------------------------------------------------------
# English -----------------------------------------------
# Fit multigroup IRT model grade is group.
mult_group_eng <- multipleGroup(data = english_items, model = 1, group = grade,
                            invariance = c(colnames(english_items),
                                           'free_means', 'free_var')) # 132 iterations

constrained_parameters_eng <- coef(mult_group_eng, simplify = TRUE)[[1]][[1]]
dif_add_eng <- DIF(mult_group_eng, c('a1', 'd'), scheme = 'drop',
                seq_state = .05)

# dif_out_eng <- get.dif.items(out.list = dif_add_eng, p.val = .05,
#                          parms = constrained_parameters_eng)
# dif_out_eng

# Freely estimate items with DIF.
model_eng <- '
 I = 1-40
 CONSTRAINB = (1-13, 15-20, 22, 23, 25, 28, 30-36, 39, a1),
    (1-13, 15-20, 22, 23, 25, 28, 30-36, 39, d)
'
mult_group_part_eng <- multipleGroup(data = english_items, model = model_eng,
                                     group = grade,
                                 invariance = c('free_means', 'free_var'),
                                 #constrain = constrain,
                                 technical = list(NCYCLES = 2000)) # 135 Iterations
parameters_eng <- coef(mult_group_part_eng, simplify = TRUE)

#--------------------------------------------------------
# Mathematics -----------------------------------------------
# Fit multigroup IRT model grade is group.
mult_group_math <- multipleGroup(data = math_items, model = 1, group = grade,
                            invariance = c(colnames(math_items),
                                           'free_means', 'free_var')) # 186 iterations

constrained_parameters_math <- coef(mult_group_math, simplify = TRUE)[[1]][[1]]
dif_add_math <- DIF(mult_group_math, c('a1', 'd'), scheme = 'drop',
               seq_state = .05)
dif_add_math

# dif_out_math <- get.dif.items(out.list = dif_add_math, p.val = .05,
#                          parms = constrained.parameters)
# dif_out_math

# Freely estimate items with DIF.
model_math <- '
 I = 1-30
 CONSTRAINB = (1, 4, 5, 8, 11, 13, 14, 17-18, 21-23, 25-30, a1),
    (1, 4, 5, 8, 11, 13, 14, 17-18, 21-23, 25-30, d)
'
mult_group_part_math <- multipleGroup(data = math_items, model = model_math,
                                      group = grade,
                                 invariance = c('free_means', 'free_var'),
                                 #constrain = constrain,
                                 technical = list(NCYCLES = 2000)) # 243 Iterations
parameters_math <- coef(mult_group_part_math, simplify = TRUE)

# probability ----
prob_item2 <- data.frame(rbind(
  cbind(probtrace(extract.item(mult_group_part_math, 2, group = 1), Theta = seq(-6, 6, .1)), theta = seq(-6, 6, .1), group = 'Grade 4'),
                         cbind(probtrace(extract.item(mult_group_part_math, 2, group = 2), Theta = seq(-6, 6, .1)), theta = seq(-6, 6, .1), group = 'Grade 5'),
                         cbind(probtrace(extract.item(mult_group_part_math, 2, group = 3), Theta = seq(-6, 6, .1)), theta = seq(-6, 6, .1), group = 'Grade 6')
                         )
                         )
prob_item2$P.0 <- as.numeric(as.character(prob_item2$P.0))
prob_item2$P.1 <- as.numeric(as.character(prob_item2$P.1))
prob_item2$theta <- as.numeric(as.character(prob_item2$theta))

p <- ggplot(prob_item2, aes(x = theta, y = P.1)) +
  geom_line(aes(group = group, color = group), size = 2) +
  scale_x_continuous("Aptitude", breaks = seq(-6, 6, 1)) +
  ylab("Probability Correct") +
  scale_color_grey("", start = 0) +
  theme_bw(base_size = 12)
ggsave(filename = "icc_math2.png", plot = p, dpi = 'retina', height = 4, width = 6,
       path = 'paper/figs')

# iteminformation ----
info_item2 <- data.frame(rbind(
  cbind(iteminfo(extract.item(mult_group_part_math, 2, group = 1), Theta = seq(-6, 6, .1)), theta = seq(-6, 6, .1), group = 'Grade 4'),
  cbind(iteminfo(extract.item(mult_group_part_math, 2, group = 2), Theta = seq(-6, 6, .1)), theta = seq(-6, 6, .1), group = 'Grade 5'),
  cbind(iteminfo(extract.item(mult_group_part_math, 2, group = 3), Theta = seq(-6, 6, .1)), theta = seq(-6, 6, .1), group = 'Grade 6')
)
)
info_item2$V1 <- as.numeric(as.character(info_item2$V1))
info_item2$theta <- as.numeric(as.character(info_item2$theta))

p <- ggplot(info_item2, aes(x = theta, y = V1)) +
  geom_line(aes(group = group, color = group), size = 2) +
  scale_x_continuous("Aptitude", breaks = seq(-6, 6, 1)) +
  ylab("Item Information") +
  viridis::scale_color_viridis("", discrete = TRUE, option = 'magma') +
  theme_bw(base_size = 12)
ggsave(filename = "info_math2.png", plot = p, dpi = 'retina', height = 4, width = 6,
       path = 'paper/figs')

# Model Implied test score ----
# test_scores <- data.frame(rbind(
#   cbind(expected.test(extract.group(mult_group_part_math, 1), Theta = seq(-6, 6, .1)), theta = seq(-6, 6, .1), group = 'Grade 4'),
#   cbind(expected.test(extract.group(mult_group_part_math, 2), Theta = seq(-6, 6, .1)), theta = seq(-6, 6, .1), group = 'Grade 5'),
#   cbind(expected.test(extract.group(mult_group_part_math, 3), Theta = seq(-6, 6, .1)), theta = seq(-6, 6, .1), group = 'Grade 6')
# )
# )

tmp <- plot(mult_group_part_math)

# tmp$panel.args
pltdata <- data.frame(lapply(tmp$panel.args, function(x) do.call(cbind, x))[[1]])
names(pltdata) <- c("theta", "tcc", "num")
pltdata$group <- paste0('Grade ', tmp$panel.args.common$groups)

p <- ggplot(pltdata, aes(x = theta, y = tcc)) +
  geom_line(aes(group = group, color = group), size = 2) +
  scale_x_continuous("Aptitude", breaks = seq(-6, 6, 1)) +
  scale_y_continuous("Model Implied Number Correct", breaks = seq(0, 30, 5),
                     limits = c(0, 30)) +
  scale_color_grey("") +
  theme_bw(base_size = 12)
ggsave(filename = "test_math.png", plot = p, dpi = 'retina', height = 4, width = 6,
       path = 'paper/figs')

# Using plink to get model implied test scores ----
library(plink)

parameters_math <- coef(mult_group_part_math, simplify = TRUE,
                        IRTpars = TRUE)

item_info <- bind_rows(
  cbind(group = 'Grade 4', drm(data.frame(parameters_math[[1]]$items[, 1:2]), seq(-6, 6, .1))@prob
        ),
  cbind(group = 'Grade 5', drm(data.frame(parameters_math[[2]]$items[, 1:2]), seq(-6, 6, .1))@prob
  ),
  cbind(group = 'Grade 6', drm(data.frame(parameters_math[[3]]$items[, 1:2]), seq(-6, 6, .1))@prob
  )
) %>%
  mutate(tcc = rowSums(select(., contains('item'))))

p <- ggplot(item_info, aes(x = theta1, y = tcc)) +
  geom_line(aes(group = group, color = group), size = 2) +
  scale_x_continuous("Aptitude", breaks = seq(-6, 6, 1)) +
  scale_y_continuous("Model Implied Number Correct", breaks = seq(0, 30, 5),
                     limits = c(0, 30)) +
  scale_color_grey("", start = 0) +
  theme_bw(base_size = 12)
ggsave(filename = "test_math.png", plot = p, dpi = 'retina', height = 4, width = 6,
       path = 'paper/figs')

#--------------------------------------------------------
# Reading -----------------------------------------------
# Fit multigroup IRT model grade is group.
mult_group_read <- multipleGroup(data = read_items, model = 1, group = grade,
                                 invariance = c(colnames(read_items),
                                                'free_means', 'free_var')) # 144 iterations

constrained_parameters_read <- coef(mult_group_read, simplify = TRUE)[[1]][[1]]
dif_add_read <- DIF(mult_group_read, c('a1', 'd'), scheme = 'drop',
                    seq_state = .05)
dif_add_read

# dif_out_read <- get.dif.items(out.list = dif_add_read, p.val = .05,
#                               parms = constrained.parameters)
# dif_out_read

# Freely estimate items with DIF.
model_read <- '
  I = 1-30
  CONSTRAINB = (2-18, 21, 24-28, 30, a1),
    (2-18, 21, 24-28, 30, d)
'
mult_group_part_read <- multipleGroup(data = read_items, model = model_read,
                                      group = grade,
                                      invariance = c('free_means', 'free_var'),
                                      #constrain = constrain,
                                      technical = list(NCYCLES = 2000)) # 144 Iterations
parameters_read <- coef(mult_group_part_read, simplify = TRUE)

#--------------------------------------------------------
# Science -----------------------------------------------
# Fit multigroup IRT model grade is group.
mult_group_sci <- multipleGroup(data = sci_items, model = 1, group = grade,
                                 invariance = c(colnames(sci_items),
                                                'free_means', 'free_var')) # 171 iterations

constrained_parameters_sci <- coef(mult_group_sci, simplify = TRUE)[[1]][[1]]
dif_add_sci <- DIF(mult_group_sci, c('a1', 'd'), scheme = 'drop',
                    seq_state = .05)
dif_add_sci

# dif_out_sci <- get.dif.items(out.list = dif_add_sci, p.val = .05,
#                               parms = constrained.parameters)
# dif_out_sci

# Freely estimate items with DIF.
model_sci <- '
  I = 1-28
  CONSTRAINB = (2-14, 16-21, 23-28, a1),
    (2-14, 16-21, 23-28, d)
'
mult_group_part_sci <- multipleGroup(data = sci_items, model = model_sci,
                                      group = grade,
                                      invariance = c('free_means', 'free_var'),
                                      #constrain = constrain,
                                      technical = list(NCYCLES = 2000)) # 122 Iterations
parameters_sci <- coef(mult_group_part_sci, simplify = TRUE)

# save models
save(mult_group_part_eng, mult_group_part_math, mult_group_part_read, mult_group_part_sci,
     file = 'Data/multiple_group_models.rda')

M2(mult_group_part_eng)
M2(mult_group_part_math)
M2(mult_group_part_read)
M2(mult_group_part_sci)

# Sex DIF ----
sex <- as.character(belin$ngender)

# English -----------------------------------------------
# Fit multigroup IRT model sex is group.
mult_group_eng <- multipleGroup(data = english_items, model = 1, group = sex,
                                invariance = c(colnames(english_items),
                                               'free_means', 'free_var')) # 30 iterations

constrained_parameters_eng <- coef(mult_group_eng, simplify = TRUE)[[1]][[1]]
dif_add_eng <- DIF(mult_group_eng, c('a1', 'd'), scheme = 'drop',
                   seq_state = .05)

# dif_out_eng <- get.dif.items(out.list = dif_add_eng, p.val = .05,
#                          parms = constrained_parameters_eng)
# dif_out_eng

# Freely estimate items with DIF.
model_eng <- '
I = 1-40
CONSTRAINB = (1-8, 10, 12, 14-16, 18-30, 32, 34, 36-38, 40, a1),
(1-8, 10, 12, 14-16, 18-30, 32, 34, 36-38, 40, d)
'
mult_group_part_eng <- multipleGroup(data = english_items, model = model_eng,
                                     group = sex,
                                     invariance = c('free_means', 'free_var'),
                                     #constrain = constrain,
                                     technical = list(NCYCLES = 2000)) # 38 Iterations
parameters_eng <- coef(mult_group_part_eng, simplify = TRUE)

# Mathematics -----------------------------------------------
# Fit multigroup IRT model grade is group.
mult_group_math <- multipleGroup(data = math_items, model = 1, group = sex,
                                 invariance = c(colnames(math_items),
                                                'free_means', 'free_var')) # 33 iterations

constrained_parameters_math <- coef(mult_group_math, simplify = TRUE)[[1]][[1]]
dif_add_math <- DIF(mult_group_math, c('a1', 'd'), scheme = 'drop',
                    seq_state = .05)
dif_add_math

# dif_out_math <- get.dif.items(out.list = dif_add_math, p.val = .05,
#                          parms = constrained.parameters)
# dif_out_math

# Freely estimate items with DIF.
model_math <- '
I = 1-30
CONSTRAINB = (1-8, 10-12, 16-20, 22, 23, 25-28, 30, a1),
(1-8, 10-12, 16-20, 22, 23, 25-28, 30, d)
'
mult_group_part_math <- multipleGroup(data = math_items, model = model_math,
                                      group = sex,
                                      invariance = c('free_means', 'free_var'),
                                      #constrain = constrain,
                                      technical = list(NCYCLES = 2000)) # 19 Iterations
parameters_math <- coef(mult_group_part_math, simplify = TRUE)

#--------------------------------------------------------
# Reading -----------------------------------------------
# Fit multigroup IRT model grade is group.
mult_group_read <- multipleGroup(data = read_items, model = 1, group = sex,
                                 invariance = c(colnames(read_items),
                                                'free_means', 'free_var')) # 50 iterations

constrained_parameters_read <- coef(mult_group_read, simplify = TRUE)[[1]][[1]]
dif_add_read <- DIF(mult_group_read, c('a1', 'd'), scheme = 'drop',
                    seq_state = .05)
dif_add_read

# dif_out_read <- get.dif.items(out.list = dif_add_read, p.val = .05,
#                               parms = constrained.parameters)
# dif_out_read

# Freely estimate items with DIF.
model_read <- '
  I = 1-30
  CONSTRAINB = (1, 4-9, 11-13, 15-20, 22, 23, 25-27, 29, a1),
    (1, 4-9, 11-13, 15-20, 22, 23, 25-27, 29, d)
'
mult_group_part_read <- multipleGroup(data = read_items, model = model_read,
                                      group = sex,
                                      invariance = c('free_means', 'free_var'),
                                      #constrain = constrain,
                                      technical = list(NCYCLES = 2000)) # 54 Iterations
parameters_read <- coef(mult_group_part_read, simplify = TRUE)

#--------------------------------------------------------
# Science -----------------------------------------------
# Fit multigroup IRT model grade is group.
mult_group_sci <- multipleGroup(data = sci_items, model = 1, group = sex,
                                invariance = c(colnames(sci_items),
                                               'free_mean', 'free_var')) # 27 iterations

constrained_parameters_sci <- coef(mult_group_sci, simplify = TRUE)[[1]][[1]]
dif_add_sci <- DIF(mult_group_sci, c('a1', 'd'), scheme = 'drop',
                   seq_state = .05)
dif_add_sci

# dif_out_sci <- get.dif.items(out.list = dif_add_sci, p.val = .05,
#                               parms = constrained.parameters)
# dif_out_sci

# Freely estimate items with DIF.
model_sci <- '
  I = 1-28
  CONSTRAINB = (1-3, 5, 6, 9-10, 13, 15-18, 20-21, 23-27, a1),
    (1-3, 5, 6, 9-10, 13, 15-18, 20-21, 23-27, d)
'
mult_group_part_sci <- multipleGroup(data = sci_items, model = model_sci,
                                     group = sex,
                                     invariance = c('free_mean', 'free_var'),
                                     #constrain = constrain,
                                     technical = list(NCYCLES = 2000)) # 39 Iterations
parameters_sci <- coef(mult_group_part_sci, simplify = TRUE)


data(ms_world) ## measles case data
data(contact_countries) ## mapping of countries in ESEN2 to countries in POLYMOD

## country-specific R0 scaling
data(polymod)

contact_r0 <- list()
for (country in survey_countries(polymod))
{
  m <- contact_matrix(survey=polymod, countries=country, n=100, symmetric=TRUE,
                      estimated.contact.age = "sample", sample.all.age.groups = TRUE,
                      age.limits=seq(0, 65, by=5))
  contact_r0[[country]] <- vapply(m$matrices, function(x) {
    as.numeric(eigen(x$matrix, only.values = TRUE)$values[1])
  }, 0)
}

contact_r0_means <- vapply(contact_r0, mean, 0)
ccr0 <- data.frame(country=names(contact_r0_means), contact_r0=contact_r0_means) %>%
  remove_rownames %>%
  mutate(rel_r0 = contact_r0 / mean(contact_r0))

cr0 <- tibble(country=factor(names(contact_countries)), polymod=contact_countries) %>%
    remove_rownames %>%
    left_join(ccr0 %>%
              dplyr::rename(polymod=country) %>%
              mutate(polymod=as.character(polymod)), by="polymod") %>%
    mutate(polymod=factor(polymod),
           country=countrycode(country, "country.name", "eurostat.name"))

model_adjImm <- sero_adjImm %>%
    gather(variable, immunity, ends_with("_immunity")) %>%
    separate(variable, c("model", "dump")) %>%
    mutate(model=recode_factor(model, adjusted="contact-adjusted", mean="plain"),
           country=countrycode(country, "country.name", "eurostat.name")) %>%
    select(-dump) %>%
    left_join(cr0, by=c("country")) %>%
    rename(scaled=rel_r0) %>%
    mutate(fixed=1) %>%
    gather(r0_model, rel_r0, fixed, scaled) %>%
    mutate(susceptibility=(1-immunity)*rel_r0) %>%
    select(-contact_r0, -rel_r0)

survey_years <- model_adjImm %>%
    group_by(country) %>%
    summarise(survey_yr=as.integer(max(year, na.rm=TRUE)))

ms_cases <- ms_world %>%
    tbl_df() %>%
    inner_join(survey_years, by=("country"))

horizon <- 10

horizon_col <- paste("years", horizon, sep=".")
case_col <- paste("cases", horizon, sep=".")
ms_cases %<>%
  replace_na(list(cases=0)) %>%
  mutate(!!horizon_col := if_else(year > survey_yr & year <= survey_yr + horizon, 1, 0),
         !!case_col := !!sym(horizon_col) * cases)

msw <- ms_cases %>%
    select(-year) %>%
    rename(year=survey_yr) %>%
    select(-starts_with("years.")) %>%
    gather(variable, cases, starts_with("cases.")) %>%
    separate(variable, c("dummy", "window"), sep="\\.") %>%
    mutate(window=as.integer(window)) %>%
    select(-dummy) %>%
    group_by(country, window, year) %>%
    summarise(sum.cases=sum(cases),
              max.cases=max(cases)) %>%
    rowwise %>%
    mutate(pop_df=list(wpp_age(country, year)),
           population=sum(pop_df$population)) %>%
    select(-pop_df) %>%
    ungroup %>%
    mutate(cases.per.million.per.year = signif(sum.cases / (population*window)*1e6),
           max.cases.per.million = signif(max.cases / (population)*1e6))

threshold_test <- seq(0.8, 1, by=0.01)

measure <- "cases.per.million.per.year"
measure_threshold <- 5
method <- "spearman"

corr_coeff <- function(df)
{
    corr <- cor.test(1 - df$susceptibility, log(df[[measure]]), method=method)
    correlation <- data.frame(corr[c("estimate", "p.value")])

    outbreaks <- df[[measure]] > measure_threshold
    immunity <- 1 - df$susceptibility
    correct_threshold <-
        lapply(threshold_test, function(t) {sum(outbreaks == (immunity < t))})
    correct <-
        data.frame(threshold=threshold_test, correct=unlist(correct_threshold))

    n <- nrow(df)
    return(tibble(correlation=list(correlation), correct=list(correct), n))
}

cc <- model_adjImm %>%
    left_join(msw, by=c("country", "year")) %>%
    group_by(sample, eqi, r0_model, model, vaccination, window) %>%
    nest %>%
    mutate(corr=map(data, corr_coeff)) %>%
    select(-data) %>%
    unnest(corr)

scorr <- cc %>%
    unnest(correlation) %>%
    group_by(eqi, r0_model, model, vaccination, window) %>%
    summarise(p.value=mean(p.value),
              median=median(estimate),
              min.estimate=quantile(estimate, 0.05),
              max.estimate=quantile(estimate, 0.95),
              n=n()) %>%
    ungroup() %>%
    arrange(median) %>%
    mutate_at(vars(5:ncol(.)), signif, digits=2)

## correlation summary table
opts_current$set(label = "correlations")
scorr %>%
    mutate(mean_ci=paste0(median, "~(", min.estimate, ", ", max.estimate, ")")) %>%
    arrange(model, r0_model, eqi) %>%
    select(`Immunity model`=model, `$R_0$ model`=r0_model, `Vaccination model`=vaccination, `Equivocal samples`=eqi,
           `Correlation~(90\\% CI)`=mean_ci) %>%
    kable("latex",
          escape=FALSE, linesep="", booktabs=TRUE,
          caption="Spearman's rank correlation between immunity estimated from nationwide serology and~(if contact-adjusted) contact studies on the one hand and the mean number of cases in the 10 years following the studies on the other. The model with the greatest absolute correlation is highlighted in bold.") %>%
    kable_styling(latex_options=c("hold_position")) %>%
    write("table_2.tex")

## misclassification error
smce <- cc %>%
    unnest(correct) %>%
    group_by(eqi, r0_model, model, vaccination, window, threshold) %>%
    dplyr::summarise(median=median(1-correct/n),
                     mean=mean(1-correct/n),
                     min=mean-sd(1-correct/n),
                     max=mean+sd(1-correct/n)) %>%
    ungroup

## figures for paper
p <- ggplot(msw %>%
            arrange(cases.per.million.per.year) %>%
            mutate(country=factor(country, levels=unique(country))),
            aes(x=country, y=100*cases.per.million.per.year)) +
    geom_bar(stat="identity") +
    geom_text(aes(label=scales::comma(max.cases)), position=position_dodge(width=0.9), vjust=-0.3) +
    expand_limits(y=50000) +
    theme(axis.text.x=element_text(angle = 45, vjust = 1, hjust = 1)) +
    scale_x_discrete("") +
    geom_vline(xintercept=9.5, linetype="dotted", lwd=0.7) +
    geom_hline(yintercept=500, linetype="dotted", lwd=0.7) +
    scale_y_log10("Cases per year per million",
                  breaks=10^(0:4), labels=10^((-2):2))
save_plot("figure_1.pdf", p, base_aspect_ratio = 1.9)

smce_select <- smce %>%
    filter(eqi == "positive", r0_model=="fixed", vaccination=="projected", threshold < 1)

p <- ggplot(smce_select, aes(x=threshold, y=mean, ymin=min, ymax=max)) +
    facet_grid(~model) +
    geom_point()  +
    geom_line() +
    geom_ribbon(alpha=0.25) +
    scale_x_continuous("Threshold level", label=scales::percent) +
    scale_y_continuous("Misclassification error")

save_plot("figure_2.pdf", p, base_aspect_ratio = 1.9, base_height = 3)

number_formatter <- function(x)
{
    return(as.character(if_else(x >= 10, round(x), if_else(x >= 1, round(x, 1), signif(x, 2)))))
}

esen2_adjImm <- model_adjImm %>%
    filter(eqi == "positive", vaccination=="projected") %>%
    group_by(country, model) %>%
    summarise(immunity=mean(immunity)) %>%
    mutate(immunity=signif(immunity, 2)) %>%
    spread(model, immunity)

## pretty format summary table
opts_current$set(label = "outbreaks")
msw %>%
    left_join(esen2_adjImm) %>%
    arrange(max.cases.per.million) %>%
    dplyr::select(country, sum.cases, max.cases, cases.per.million.per.year, max.cases.per.million,
           `contact-adjusted`, plain) %>%
    mutate(country=as.character(country),
           sum.cases=as.integer(sum.cases),
           max.cases=as.integer(max.cases),
           cases.per.million.per.year=formattable(cases.per.million.per.year, formatter=number_formatter),
           max.cases.per.million=formattable(max.cases.per.million, formatter=number_formatter)) %>%
    mutate_all(linebreak) %>%
    kable("latex",
          col.names=linebreak(c("Country",
                                "Total\n(10 years)",
                                "Maximum\nannual",
                                "Mean annual\n(per million)",
                                "Maximum\nannual\n(per million)",
                                "contact-\nadjusted",
                                "plain"),
                              align="c"),
          escape=FALSE, linesep="", booktabs=TRUE,
          caption="Measles cases in the 10 years following the ESEN2 serological study, and mean estimated population immunity~(contact-adjusted or not, with fixed $R_0$ and equivocal samples interpreted as positive) based on the study and adjusted for vaccination uptake.") %>%
    add_header_above(c(" ", Cases=4, Immunity=2)) %>%
    kable_styling(latex_options=c("hold_position")) %>%
    ## kable_as_image("esen2") %>%
    write("table_1.tex")


#' Optimal Leader/Mentor Matching
#'
#' Implementes the algorithm described in Valente and Davis (1999)
#'
#' @template graph_template
#' @param n Number of leaders
#' @param cmode Passed to \code{\link{dgr}}.
#' @param lead.ties.method Passed to \code{\link{rank}}
#' @param geodist.args Passed to \code{\link{approx_geodesic}}.
#'
#' @details The algorithm works as follows:
#' \enumerate{
#'   \item Find the top \code{n} individuals ranking them by \code{dgr(graph, cmode)}.
#'   The rank is computed by the function \code{\link{rank}}. Denote this set \code{M}.
#'   \item Compute the geodesic matrix.
#'   \item For each \code{v in V} do:
#'
#'   \enumerate{
#'     \item Find the mentor \code{m in M} such that is closest to \code{v}
#'     \item Were there a tie, choose the mentor that minimizes the average
#'     path length from \code{v}'s direct neighbors to \code{m}.
#'     \item If there are no paths to any member of \code{M}, or all have the
#'     same average path length to \code{v}'s neighbors, then assign one
#'     randomly.
#'   }
#' }
#'
#' @return An object of class \code{diffnet_mentor} and \code{data.frame} with the following columns:
#' \item{name}{Character. Labels of the vertices}
#' \item{degree}{Numeric. Degree of each vertex in the graph}
#' \item{iselader}{Logical. \code{TRUE} when the vertex was picked as a leader.}
#' \item{match}{Character. The corresponding matched leader.}
#'
#' The object also contains the following attributes:
#'
#' \item{nleaders}{Integer scalar. The resulting number of leaders (could be greater than \code{n})}.
#' \item{graph}{The original graph used to run the algorithm.}
#'
#' @references
#' Valente, T. W., & Davis, R. L. (1999). Accelerating the Diffusion of
#' Innovations Using Opinion Leaders. The ANNALS of the American Academy of
#' Political and Social Science, 566(1), 55–67.
#' \doi{10.1177/000271629956600105}
#' @examples
#' # A simple example ----------------------------------------------------------
#' set.seed(1231)
#' graph <- rgraph_ws(n=50, k = 4, p = .5)
#'
#' # Looking for 3 mentors
#' ans <- mentor_matching(graph, n = 3)
#'
#' head(ans)
#' table(ans$match) # We actually got 9 b/c of ties
#'
#' # Visualizing the mentor network
#' plot(ans)
#'
#' @export
mentor_matching <- function(
  graph,
  n,
  cmode            = "indegree",
  lead.ties.method = "average",
  geodist.args     = list()
) {

  cls <- class(graph)

  if (any(c("dgCMatrix", "matrix", "array") %in% cls)) {
    # Adding labels in case there aren't any
    if (!length(rownames(graph))) {
      warning("-graph- as no labels (rownames). We'll add some from 1 to n.")
      dimnames(graph) <- list(1:nnodes(graph), 1:nnodes(graph))
    }
  }

  if (any(c("dgCMatrix", "matrix") %in% cls)) {

    # Matrix method
    .mentor_matching(graph, n, cmode, lead.ties.method, geodist.args)

  } else if ("list" %in% cls) {

    # List method
    lapply(graph, .mentor_matching, n = n,
           cmode = cmode, lead.ties.method = lead.ties.method,
           geodist.args = geodist.args)

  } else if ("array" %in% cls) {

    # Array method
    apply(graph, 3, .mentor_matching, n = n,
          cmode = cmode, lead.ties.method = lead.ties.method,
          geodist.args = geodist.args)

  } else if ("diffnet" %in% cls) {

    # diffnet method
    g <- graph$graph
    g <- lapply(g, `dimnames<-`, value = list(nodes(graph), nodes(graph)))
    lapply(g, .mentor_matching, n = n,
           cmode = cmode, lead.ties.method = lead.ties.method,
           geodist.args = geodist.args)

  } else stopifnot_graph(graph)

}

.mentor_matching <- function(
  graph,
  n,
  cmode            = "indegree",
  lead.ties.method = "average",
  geodist.args     = list()
) {

  # Step 1. Find the pcent with highest
  d   <- dgr(graph, cmode = cmode)
  r   <- -rank(d, ties.method = lead.ties.method)
  r   <- as.integer(as.factor(r))
  top <- which(r <= n)

  # Step 2: Match each individual with their closest one
  G   <- do.call(
    approx_geodist,
    c(list(graph = as.matrix(graph)), geodist.args)
  )

  ans <- sapply(1:nnodes(graph), function(i) {
    x <- which(G[i,top] == min(G[i,top]))

    # If there are any ties, then solve them by taking a look at i's
    # neighbors
    if (length(x) > 1) {

      # Picking neighbors
      j <- which(graph[i,-top] != 0)

      # If all of them are top
      if (!length(j))
        return(sample(top, size = 1))

      # Average pathlength per top
      j <- sapply(top, function(h) {
        mean(G[j,h])
      })

      # Choose the min
      top[which.min(j)]

    } else top[x]
  })

  # Mentors should be assigned to them selfs
  ans[top] <- top

  # Returning
  structure(
    data.frame(
      name     = nodes(graph),
      degree   = d,
      isleader = 1:nnodes(graph) %in% top,
      match    = nodes(graph)[ans],
      stringsAsFactors = FALSE
    ),
    class    = c("diffnet_mentor", "data.frame"),
    nleaders = length(top),
    graph    = graph
  )

}

#' @export
#' @rdname mentor_matching
leader_matching <- mentor_matching

#' @export
#' @param x An object of class \code{diffnet_mentor}.
#' @template plotting_template
#' @param lead.cols Character vector of length \code{attr(x,"nleaders")}. Colors
#' to be applied to each group. (see details)
#' @param vshapes Character scalar of length 2. Shapes to identify leaders (mentors)
#' and followers respectively.
#' @param add.legend Logical scalar. When \code{TRUE} generates a legend to distinguish
#' between leaders and followers.
#' @param y Ignored.
#' @param ... Further arguments passed to \code{\link[igraph:plot.igraph]{plot.igraph}}
#' @param main Character scalar. Passed to \code{\link[graphics:title]{title}}
#' @rdname mentor_matching
plot.diffnet_mentor <- function(
  x,
  y            = NULL,
  vertex.size  = "degree",
  minmax.relative.size = getOption("diffnet.minmax.relative.size", c(0.01, 0.04)),
  lead.cols    = grDevices::topo.colors(attr(x, "nleaders")),
  vshapes      = c(Leader="square", Follower="circle"),
  add.legend   = TRUE,
  main         = "Mentoring Network",
  ...) {

  igraph.args <- list(...)
  oldpar <- graphics::par(no.readonly = TRUE)
  on.exit(graphics::par(oldpar))
  graphics::par(xpd = NA)

  set_igraph_plotting_defaults("igraph.args")

  # Creating igraph obj
  ig <- cbind(
    as.character(x[["name"]]),
    as.character(x[["match"]])
  )

  ig <- edgelist_to_adjmat(ig)
  ig <- ig[x[["name"]],][,x[["name"]]]
  ig <- igraph::graph_from_adjacency_matrix(ig, weighted = NULL)

  # Creating plot
  graphics::plot.new()
  graphics::plot.window(xlim = c(-1,1), ylim = c(-1,1))

  igraph::V(ig)$shape <- vshapes[2-x[["isleader"]]]

  igraph.args$vertex.size <- rescale_vertex_igraph(
    compute_vertex_size(ig, vertex.size),
    minmax.relative.size = minmax.relative.size
  )

  igraph.args$vertex.color <- lead.cols[as.integer(factor(x[["match"]]))]

  do.call(igraph::plot.igraph, c(list(x = ig), igraph.args))

  if (add.legend) {

    # Checking names
    if (!length(names(vshapes)))
      names(vshapes) <- c("Leader", "Follower")

    A<-B<-1
    ig <- igraph::make_graph(~A,B)
    igraph::V(ig)$name  <- names(vshapes)
    igraph::V(ig)$color <- "gray"
    igraph::V(ig)$label.color <- "black"
    igraph::V(ig)$shape <- vshapes
    igraph::V(ig)$size  <- 2
    plot(ig, layout = rbind(c(-.4, -1.3), c(.15, -1.3)), add=TRUE,
         vertex.size = 5, rescale=FALSE, vertex.label.dist = 1, vertex.label.degree=0)

  }

  title(main=main)

  # Returning
  invisible(x)

}


# lhl.R

# Church two step breakpoint algorithm, from Church et al, 1994.

lhl_old <- function(r_times){

  # initial values
  # s1 <- 0 # start
  s2 <- 0 # stop
  t1 <- 0 # first low rate duration
  t2 <- 0 # high rate duration
  t3 <- 0 # second low rate duration
  r1 <- 0 # first low rate
  r2 <- 0 # high rate
  r3 <- 0 # second low rate
  index_s1 <- 0 # index to get start (inner for loop)
  index_s2 <- 0 # index to get stop (outer for loop)
  algorithm_s1 <- 0 # as above, indexed by index_s1
  algorithm_s2 <- 0
  end_trial <- 180
  nr <- length(r_times) # number of responses
  r <- nr/180 # get overall response rate

  # 'if' conditional states that trials must have more than 3 responses
  if (nr > 3) {

    # loop through response times, except the last
    # then choose best t1 (inner for loop),
    # then get best s2 estimate (outer for loop)

    for (i in 1:(nr - 1)) {

      s2[i] <- r_times[i + 1]
      t3[i] <- end_trial - s2[i]

      if (t3[i] <= 0) {
        r3[i] <- 0 # necessary to avoid division by 0
        t3[i] <- 0
      } else {
        r3[i] <- sum(r_times > s2[i])/t3[i]
      }

      for (j in seq_along(s2)) { # loop through putative s2 and choose t1

        t1[j] <- r_times[j] # This seems wrong! j = 1, 2, 3..., not the values of s2
        r1[j] <- sum(r_times <= t1[j])/t1[j]
        t2[j] <- s2[i] - t1[j] # high-rate duration

        if (t2[j] == 0) {
          r2[j] <- 0 # necessary to avoid division by 0
        } else {
          r2[j] <- sum(r_times > t1[j] & r_times <= s2[i])/t2[j]
        }

        algorithm_s1[j] <- t1[j]*(r - r1[j]) + t2[j]*(r2[j] - r) + t3[i]*(r - r3[i])
        index_s1 <- which(algorithm_s1 == max(algorithm_s1,na.rm = T))
        # some times two indexes with same algorithm value
        # get the first of them
        if(length(index_s1) > 1){
          index_s1 <- min(index_s1)
        }

      } # end inner loop (get s1 value)

      algorithm_s2[i] <- t1[index_s1]*(r - r1[index_s1]) + t2[i]*(r2[i] - r) + t3[i]*(r - r3[i])

    } # end outer for loop (get s2 value after s1)

    index_s2 <- which(algorithm_s2 == max(algorithm_s2, na.rm = T))

    if (length(index_s2) > 1) {
      index_s2 <- min(index_s2)
    }

    start <- t1[index_s1]
    stop <- s2[index_s2]
    mid <- (start + stop)/2
    low_rate_1 <- sum(r_times <= start)/start
    low_rate_2 <- sum(r_times > stop)/(end_trial - stop)
    spread <- stop - start

    high_rate <- sum(r_times > start & r_times <= stop)/spread

    bpts <-
      data.frame(start = start,
                 stop = stop,
                 mid = mid,
                 spread = spread,
                 high_rate = high_rate,
                 r1 = low_rate_1,
                 r3 = low_rate_2)

    bpts
  } # end if

}


# Gamlss estimation of gene noise for each gene for COVID19

library(edgeR)
library(gamlss)
library(gtools)

setwd("/media/yuri/Data/home1/GNI_data/infection/ResultsSciRep")
load("COVID19_RNAseq.Rdat")

################################################################################
# Functions for GAMLSS analysis
# gNBI.RS - the Rigby and Stasinopoulos algorithm for GAMLSS
gNBI.RS = function(dat, f1, f2){
  res = tryCatch(
    gamlss::gamlss(f1, sigma.fo = f2, data = dat, family = NBI(), method = RS(), n.cyc = 500),
  warning = function(w) NULL, error = function(e) NULL)
  res
}

# gNBI.CG -  the Cole and Green algorithm for GAMLSS
gNBI.CG = function(dat, f1, f2){
  res = tryCatch(
    gamlss::gamlss(f1, sigma.fo = f2, data = dat, family = NBI(), method = CG(), n.cyc = 500),
  warning = function(w) NULL, error = function(e) NULL)
  res
}

# Gamlss estimation of gene noise for each gene for COVID19
gene_noise_COVID <- mclapply(seq(nrow(DGE_RNAcounts$counts)), function(i) {

    cat(i, "\r")

    # COVID - data.frame
    # y - RNA counts
    # x - fixed effect factor (COVID19 mild/severe)
    # ofs - offset log(library size x normalization factor), see edgeR
    # Sex - gender
    # age - age
    # rnd - Sex:age interaction was used as random effect

    COVID = data.frame(y = DGE_RNAcounts$counts[i,],
      x = factor(DGE_RNAcounts$samples$stage),
      ofs = DGE_RNAcounts$samples$offset,
      Sex = DGE_RNAcounts$samples$Sex,
      age = DGE_RNAcounts$samples$age
    )
    COVID$age[is.na(COVID$age)] = median(COVID$age[!is.na(COVID$age)])
    COVID$age = quantcut(COVID$age, q=10)
    COVID$rnd = paste0(COVID$Sex, ":", COVID$age)

    # f1 - gamlss formula for mu
    f1 = formula(y ~ x + random(factor(rnd)) + offset(ofs) )
    # f2 - gamlss formula for sigma
    f2 = formula(y ~ x + random(factor(rnd)))

    # gamlss model
    # m0 - model for mu and sigma with x fixed factor effects: COVID stage and random factor effects rnd: Sex:age
    sink("/dev/null")

    m0 = gNBI.RS(COVID, f1, f2)

    if(is.null(m0)) { m0 = gNBI.CG(COVID, f1, f2)  }

    sink()

    # results:
    # mu_mild - mean gene expression for mild COVID19
    # mu_severe - mean gene expression for severe COVID19
    # bcv_mild - biological coefficient of variation of gene expression for mild COVID19
    # bcv_severe - biological coefficient of variation of gene expression for severe COVID19
    # p_mu - significance of COVID19 effect (mild vs severe) on mean gene expression
    # p_bcv - significance of COVID19 effect (mild vs severe) on gene expression noise (bcv - biological coefficient of variation)

    res = data.frame(mu_mild = NA, mu_severe = NA, bcv_mild = NA, bcv_severe = NA, p_mu = NA, p_bcv=NA)

    if(!is.null(m0)) {
      sink("/dev/null")
        m0s = summary(m0, "qr", save = T)
        mu = exp(cumsum(m0s$mu.coef.table[,1]))*1e06
        bcv = sqrt(exp(cumsum(m0s$sigma.coef.table[,1])))
        p_mu = m0s$mu.coef.table[2,4]
        p_bcv = m0s$sigma.coef.table[2,4]
        res = data.frame(mu_mild = mu[[1]], mu_severe = mu[[2]],
            bcv_mild = bcv[[1]], bcv_severe = bcv[[2]],
            p_mu = p_mu, p_bcv=p_bcv)
      sink()
    }

    res

}, mc.cores = 4 )

gene_noise_COVID <- do.call(rbind, gene_noise_COVID)
rm(f1, f2, gNBI.CG, gNBI.RS)

setwd("/media/yuri/Data/home1/GNI_data/infection/ResultsSciRep")
save.image("COVID19_gene_noise_Figure6A.Rdat")


valoreAtteso <- 2.81

n <- 5

domanda1 <- 4

domanda2 <- 4

risposta1 <- 1 - (ppois(domanda1, valoreAtteso) ^ n);

risposta2 <- 1- ppois(domanda2*n, valoreAtteso*n);

print(risposta1)

print(risposta2)