#' Population interpolation annual and single age in MSDem
#'
#' This function allows you to calculate population size by sex or by regions using the MSDem output
#' @param res1 data
#' @param agel lower limit - default is 0
#' @param ageu upper limit - default it 'max'
#' @param period specific periods - default is NULL
#' @param sex specific sex - default is NULL
#' @param bysex group by sex - default is FALSE
#' @param reg specific region(s)
#' @param byreg group by regions - default is FALSE
#' @param resi specific residence(s)
#' @param byresi group by residences - default is FALSE
#' @return R list with five data.table 1) var_def 2) state_space 3) mig_dom 4) mig_int 5) results
#' @keywords read
#' @export
#' @examples

# 1. The initial data as you have seen are for 5-year periods and 5-year intervals (on 1 july of each year),
#
# 2. so the interpolation is done first to create a cross-sectional annual time series of 5-year age groups
# (1-BeersOInterpol.r and IND_Pop2015B5_1.7.csv as sample input test data for India population both sexes for 2015 WPP revision),
#
# 3. and then it gets transformed into single ages (e.g., IND_Pop2015B1x1-step1-sprague.csv),
#
# 4. and interpolated by cohort for the pivotal years ending in 0 and 5 for which the estimates/projections are available
#     (2-SpragueSplit.r).
#
# At very old ages some alternative method with additional constraint needs to be added
# to avoid implausible negative populations (e.g., IND_Pop2015B1x1-step2-pchipGE90.csv).
#
# A special provision is needed to deal with the youngest age group and oldest age groups which cannot be
# interpolated by cohort.
#
# The cohort interpolation can be done using linear or exponential interpolation.
# In previous WPP revisions the interpolation used was linear, but exponential interpolation alleviates
# some of the artifact fluctuations.

popinterpkc <- function(x){
  x<<-x
  head(x)
  # stop()
  #1. The initial data as you have seen are for
  #5-year periods and 5-year intervals (on 1 july of each year),

  iage <- sort(unique(x$age))
  iper <- unique(x$period)
  x1<-x%>%select(period,age,pop)%>%spread(period,pop)%>%select(-age)

  # xx_8_90 <- x1[-19,8]*(x1[-1,8]/x1[-19,7])
  # xx_age0_4 <- (x1[1,8]/sum(x1[5:8,8]))*sum(xx_8_90[4:7,1])
  # x1[,9] <- rbind(xx_age0_4,xx_8_90)
  #colnames(x1)[6] <- 2036
  x1 <- as.matrix(x1)
  row.names(x1) <- iage

  # 2. so the interpolation is done first to create a cross-sectional annual time series of 5-year age groups
  # (1-BeersOInterpol.r and IND_Pop2015B5_1.7.csv as sample input test data for India population both sexes for 2015 WPP revision),
  tp <- t(x1)
  YEAR <- as.numeric(substr(rownames(tp),1,4))
  FYEAR <- min(YEAR) #2011
  LYEAR <- max(YEAR) #2021
  ## dimensions
  NY <- 5                        # Number of years in period
  NCOL <- dim(tp)[2]             # number of data columns/number of countries/time series
  NYEAR5 <- dim(tp)[1]           # number of five year period
  NYEAR1 <- (NYEAR5 - 1) * 5 + 1 # number of single years
  ## Beers Ordinary Interpol
  bc <- c(
    1.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,
    0.6667,  0.4969, -0.1426, -0.1006,  0.1079, -0.0283,
    0.4072,  0.8344, -0.2336, -0.0976,  0.1224, -0.0328,
    0.2148,  1.0204, -0.2456, -0.0536,  0.0884, -0.0244,
    0.0819,  1.0689, -0.1666, -0.0126,  0.0399, -0.0115,
    0.0000,  1.0000,  0.0000,  0.0000,  0.0000,  0.0000,
    -0.0404,  0.8404,  0.2344, -0.0216, -0.0196,  0.0068,
    -0.0497,  0.6229,  0.5014, -0.0646, -0.0181,  0.0081,
    -0.0389,  0.3849,  0.7534, -0.1006, -0.0041,  0.0053,
    -0.0191,  0.1659,  0.9354, -0.0906,  0.0069,  0.0015,
    0.0000,  0.0000,  1.0000,  0.0000,  0.0000,  0.0000,
    0.0117, -0.0921,  0.9234,  0.1854, -0.0311,  0.0027,
    0.0137, -0.1101,  0.7194,  0.4454, -0.0771,  0.0087,
    0.0087, -0.0771,  0.4454,  0.7194, -0.1101,  0.0137,
    0.0027, -0.0311,  0.1854,  0.9234, -0.0921,  0.0117,
    0.0000,  0.0000,  0.0000 , 1.0000,  0.0000,  0.0000,
    0.0015,  0.0069, -0.0906 , 0.9354,  0.1659, -0.0191,
    0.0053, -0.0041, -0.1006 , 0.7534,  0.3849, -0.0389,
    0.0081, -0.0181, -0.0646 , 0.5014,  0.6229, -0.0497,
    0.0068, -0.0196, -0.0216 , 0.2344,  0.8404, -0.0404,
    0.0000,  0.0000,  0.0000,  0.0000,  1.0000,  0.0000,
    -0.0115,  0.0399, -0.0126, -0.1666,  1.0689,  0.0819,
    -0.0244,  0.0884, -0.0536, -0.2456,  1.0204,  0.2148,
    -0.0328,  0.1224, -0.0976, -0.2336,  0.8344,  0.4072,
    -0.0283,  0.1079, -0.1006, -0.1426,  0.4969,  0.6667,
    0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  1.0000
  )

  ## Format for Beers ordinary coefficients 26 x 6 fixed
  ##first part is added
  bm <- matrix(bc,26,6,byrow = T)

  # number of middle panels
  MP <- NYEAR5 - 5 #Issue, I have NYEARS = 3

  ## creating a beers coefficient matrix for single years
  bcm <- array(0, dim = c(NYEAR1,NYEAR5))

  ## inserting first two panels
  bcm[1:10,1:6] <- bm[1:10,]

  # inserting middle panels
  for (i in (1:MP))
  {
    # calculate the slices and add middle panels accordingly
    bcm[((i + 1)*NY + 1):((i + 2)*NY), i:(i + NY)] <- bm[11:15,]
  }
  ## insert last two panels
  bcm[((NYEAR5 - 3)*NY + 1):(NYEAR1),MP:(MP + NY)]<- bm[16:26,]
  options(max.print = 10000000)
  pop <- bcm %*% as.matrix(tp)
  colnames(pop) <- colnames(tp)
  rownames(pop) <- c(FYEAR:LYEAR)

  tp <-t(pop)
  Age5 <- as.numeric(row.names(tp))

  return(data.frame(age=Age5,tp))

}
# At very old ages some alternative method with additional constraint needs to be added
# to avoid implausible negative populations (e.g., IND_Pop2015B1x1-step2-pchipGE90.csv).
#
# A special provision is needed to deal with the youngest age group and oldest age groups which cannot be
# interpolated by cohort.
#
# The cohort interpolation can be done using linear or exponential interpolation.
# In previous WPP revisions the interpolation used was linear, but exponential interpolation alleviates
# some of the artifact fluctuations.

# births.interp <-function(x) {
#   ########################################################################
#   ## Interpolation of of event data (five year periods)
#   ## fifth/single years by Beers Modified six-term formula
#   ## (Siegel and Swanson, 2004, p. 729)
#   ## This formula applies some smoothing to the interpolant, which is
#   ## recommended for time series of events with some dynamic
#   ## R implementation by Thomas Buettner (21 Oct. 2015)
#   ########################################################################
#
#
#
#   x <<- x
#   tp <- x$births
#   #stop("..")
#   ## interpolation period
#   YEAR1 <- (x$year)
#   YEAR2 <- (x$year)+5
#   YEAR <- 0.5 + (YEAR1 + YEAR2)/2
#
#   FYEAR <- min(YEAR1) #1950
#   LYEAR <- max(YEAR2) #2100
#   LYEAR1 <- LYEAR - 1
#
#   ## dimensions
#   NCOL =1
#   #NCOL <- dim(tp)[2]   ## countries or trajectories
#   #NAG5 <- dim(tp)[1]   ## age or time
#   NAG5 = length(YEAR1)
#   # number of single year or single age groups
#   NAG1 <- NAG5 * 5
#
#   ## Beers Modified Split
#   bc <- c(
#     0.3332, -0.1938,  0.0702, -0.0118,  0.0022 ,
#     0.2569, -0.0753,  0.0205, -0.0027,  0.0006 ,
#     0.1903,  0.0216, -0.0146,  0.0032, -0.0005 ,
#     0.1334,  0.0969, -0.0351,  0.0059, -0.0011 ,
#     0.0862,  0.1506, -0.0410,  0.0054, -0.0012 ,
#
#     0.0486,  0.1831, -0.0329,  0.0021, -0.0009 ,
#     0.0203,  0.1955, -0.0123, -0.0031, -0.0004 ,
#     0.0008,  0.1893,  0.0193, -0.0097,  0.0003 ,
#     -0.0108,  0.1677,  0.0577, -0.0153,  0.0007 ,
#     -0.0159,  0.1354,  0.0972, -0.0170,  0.0003 ,
#
#     -0.0160,  0.0973,  0.1321, -0.0121, -0.0013 ,
#     -0.0129,  0.0590,  0.1564,  0.0018, -0.0043 ,
#     -0.0085,  0.0260,  0.1650,  0.0260, -0.0085 ,
#     -0.0043,  0.0018,  0.1564,  0.0590, -0.0129 ,
#     -0.0013, -0.0121,  0.1321,  0.0973, -0.0160 ,
#
#     0.0003, -0.0170,  0.0972,  0.1354, -0.0159 ,
#     0.0007, -0.0153,  0.0577,  0.1677, -0.0108 ,
#     0.0003, -0.0097,  0.0193,  0.1893,  0.0008 ,
#     -0.0004, -0.0031, -0.0123,  0.1955,  0.0203 ,
#     -0.0009,  0.0021, -0.0329,  0.1831,  0.0486 ,
#
#     -0.0012,  0.0054, -0.0410,  0.1506,  0.0862 ,
#     -0.0011,  0.0059, -0.0351,  0.0969,  0.1334 ,
#     -0.0005,  0.0032, -0.0146,  0.0216,  0.1903 ,
#     0.0006, -0.0027,  0.0205, -0.0753,  0.2569 ,
#     0.0022, -0.0118,  0.0702, -0.1938,  0.3332
#   )
#   ## standard format for Beers coefficients
#   bm <- matrix(bc,25,5,byrow = T)
#
#   ## Age vector
#   a <- seq(0, (NAG5 - 1)*5, by = 5)
#
#   # number of middle panels
#   MP <- NAG5 - 5 + 1
#
#   ## creating a beers coefficient matrix for 18 5-year age groups
#   bcm <- array(0, dim = c(NAG1,NAG5))
#
#   ## insert first two panels
#   bcm[1:10,1:5] <- bm[1:10,]
#
#   for (i in (1:MP))
#   {
#     # calculate the slices and add middle panels accordingly
#     bcm[((i + 1)*5 + 1):((i + 2)*5), i:(i + 4)] <- bm[11:15,]
#   }
#
#   ## insert last two panels
#   bcm[((NAG5 - 2)*5 + 1):(NAG5*5),MP:(MP + 4)] <- bm[16:25,]
#
#   options(max.print = 10000000)
#
#   pop <- bcm %*% as.matrix(tp)
#
#   ## write un-shifted results
#   ## write.csv(pops, ofn)
#
#   ## shifting the interpolant by half a year forward
#   ## In general, each interval is halved and the the halves are recombined to form a calendar year.
#   ## The first missing half year is assumed to be equal the half of the first interval.
#   ## This means simply that the first year is equal to the first (shifted) interval
#   ## The implementation used vector arithmetic by constructing a parallel data array
#   ## with the first element equal to the original first interval,
#   ## and filling the rest with the original data up to n-1 elements
#   ## Adding the two data structures and dividing the result by two
#   ## produces the shifted time reference.
#
#   pop2 <- array(0, dim = c(NAG1,NCOL))
#   pop2[1,] <- pop[1,]
#   pop2[2:NAG1,] <- pop[1:(NAG1 - 1),]
#   pops <- (pop + pop2)*0.5
#
#   return(data.frame(value=pops)%>%mutate(year=seq(FYEAR,LYEAR-1,by=1)))
#
# }


# Load the rjags library
library('rjags')

# Convert to a list
make_list <- function(draw)
{
	results = list()
	for(name in names(draw))
	{
		# Extract "chain 1"
		results[[name]] = as.array(draw[[name]][,,1])

		# Transpose 2D arrays
		if(length(dim(results[[name]])) == 2)
			results[[name]] = t(results[[name]])
	}
	return(results)
}

# Load data from file
source('data.txt')

# Run model 1 and save results
m = jags.model(file='model1.txt', inits=list(.RNG.seed=42, .RNG.name="base::Mersenne-Twister"), data=list(N1=data$N1, N2=data$N2))
update(m, 10000)
draw = jags.samples(m, 50000, thin=10,
		variable.names = c('mu1', 'mu2', 'sigma'))
results = make_list(draw)
chains = array(NA, dim=c(5000, 3))
chains[,1] = results$mu1
chains[,2] = results$mu2
chains[,3] = results$sigma
write.table(chains, file='prior1.txt', row.names=FALSE, col.names=FALSE)

# Run model 2 and save results
m = jags.model(file='model2.txt', inits=list(.RNG.seed=42, .RNG.name="base::Mersenne-Twister"), data=list(N1=data$N1, N2=data$N2))
update(m, 10000)
draw = jags.samples(m, 50000, thin=10,
		variable.names = c('mu1', 'mu2', 'sigma'))
results = make_list(draw)
chains = array(NA, dim=c(5000, 3))
chains[,1] = results$mu1
chains[,2] = results$mu2
chains[,3] = results$sigma
write.table(chains, file='prior2.txt', row.names=FALSE, col.names=FALSE)

# Run model 3 and save results
m = jags.model(file='model3.txt', inits=list(.RNG.seed=42, .RNG.name="base::Mersenne-Twister"), data=list(N1=data$N1, N2=data$N2))
update(m, 10000)
draw = jags.samples(m, 50000, thin=10,
		variable.names = c('mu1', 'mu2', 'sigma'))
results = make_list(draw)
chains = array(NA, dim=c(5000, 3))
chains[,1] = results$mu1
chains[,2] = results$mu2
chains[,3] = results$sigma
write.table(chains, file='prior3.txt', row.names=FALSE, col.names=FALSE)

# Run model 1 and save results
m = jags.model(file='model1.txt', inits=list(.RNG.seed=42, .RNG.name="base::Mersenne-Twister"), data=data)
update(m, 10000)
draw = jags.samples(m, 100000, thin=100,
		variable.names = c('mu1', 'mu2', 'sigma'))
results = make_list(draw)
chains = array(NA, dim=c(1000, 3))
chains[,1] = results$mu1
chains[,2] = results$mu2
chains[,3] = results$sigma
write.table(chains, file='chains1.txt', row.names=FALSE, col.names=FALSE)
print(mean(results$mu1 < results$mu2))
print(mean(results$mu1 == results$mu2))
print(mean(results$mu1 > results$mu2))

# Run model 2 and save results
m = jags.model(file='model2.txt', inits=list(.RNG.seed=42, .RNG.name="base::Mersenne-Twister"), data=data)
update(m, 10000)
draw = jags.samples(m, 100000, thin=100,
		variable.names = c('mu1', 'mu2', 'sigma'))
results = make_list(draw)
chains = array(NA, dim=c(1000, 3))
chains[,1] = results$mu1
chains[,2] = results$mu2
chains[,3] = results$sigma
write.table(chains, file='chains2.txt', row.names=FALSE, col.names=FALSE)
print(mean(results$mu1 < results$mu2))
print(mean(results$mu1 == results$mu2))
print(mean(results$mu1 > results$mu2))

# Run model 3 and save results
m = jags.model(file='model3.txt', inits=list(.RNG.seed=42, .RNG.name="base::Mersenne-Twister"), data=data)
update(m, 10000)
draw = jags.samples(m, 100000, thin=100,
		variable.names = c('mu1', 'mu2', 'sigma'))
results = make_list(draw)
chains = array(NA, dim=c(1000, 3))
chains[,1] = results$mu1
chains[,2] = results$mu2
chains[,3] = results$sigma
write.table(chains, file='chains3.txt', row.names=FALSE, col.names=FALSE)
print(mean(results$mu1 < results$mu2))
print(mean(results$mu1 == results$mu2))
print(mean(results$mu1 > results$mu2))


# take input from the user
num = as.integer(readline(prompt = "Enter a number: "))
if(num < 0) {
print("Enter a positive number")
} else {
sum = (num * (num + 1)) / 2;
print(paste("The sum is", sum))
}


REBOL
[
    title: "Code to implement printf natively"
]

dbg: [ here: ( print here ) ]

format: func [
    fmt [string!] {Format to print}
    data [ block!] {Block of data to put into fmt}
    /local
	;o
][
    o: context [
	str: copy ""
	char: none

	val: fills: none

	fillchar: #" "
	align-char: none
	n-space: 0
	n-fracts: 6
	fmt-char: none

	digit: charset [ #"0" - #"9" ]

	data-pattern: [
	    ( align-char: fillchar: signchar: none )
	    #"%"
	    opt [
		[ copy align-char #"-" ]
		|
		[ copy fillchar #"0"   ]
		| copy signchar #"+"
	    ]
	    copy n-space any digit
	    opt [
		#"." copy n-fracts any digit
		]
	    copy fmt-char [
		#"f"
		| #"g"
		| #"e"
		| #"E"
		| #"d"
		| #"i"
		| #"s"
	    ]
	    (
		n-space: to-integer any [ n-space 0 ]
		n-fracts: to-integer any [ n-fracts 6 ]

		val: first+ data
		unless val [
		    make error! "Not enough data to print, number of specifiers larger than data"
		]

		val: switch fmt-char [
		    "s"		[ to-string val ]
		    "d" "i"	[ num-to-string-d abs val ]
		    "f"		[ num-to-string-f abs val n-fracts ]
		    "e" "E"	[ num-to-string-e abs val n-fracts fmt-char  ]
		]

		fills: max 0 n-space - length? val
		either align-char == #"+" [
		    insert/dup tail str fillchar  fills
		    append str val
		][
		    append str val
		    insert/dup tail str fillchar  fills
		]
	    )
	]

	pattern: [
	    any [ data-pattern | copy char skip ( append str char ) ]
	]

	num-to-string-d: func [ num [ integer! ] /local str ] [
	    str: copy ""

	    unless num >= 0 [
		append str "-"
		str: next str
		num: negate num
	    ]
	    until [
		frac: mod num 10
		insert str  round/floor frac
		num: num - frac
		num: num / 10
		num < 1.0
	    ]
	    head str
	]

	num-to-string-f: func [ num n-fracts /local str ][
	    str: copy ""

	    unless num >= 0 [
		append str "-"
		str: next str
		num: negate num
	    ]

	    num: num * ( 10.0 ** n-fracts )
	    loop n-fracts [
		frac: mod num 10
		insert str  round/half-ceiling frac
		num: num - frac
		num: num / 10
	    ]
	    insert str #"."
	    until [
		frac: mod num 10
		insert str  round/floor frac
		num: num - frac
		num: num / 10
		num < 1.0
	    ]
	    head str
	]
	num-to-string-e: func [
	    num n-fracts modifier
	    /local str  n
	] [
	    str: copy ""
	    n: round/floor log-10 abs num
	    num: num / (10.0 ** n )
	    str: num-to-string-f num  n-fracts
	    append str modifier
	    append str n-fracts
	]

	parse/all/case fmt pattern
    ]

    return o/str
]

test-base: func [ fmt dta] [
    prin my: format fmt dta
    prin std: sprintf join [ fmt ] dta
    either my == std [
	print "-- OK"
    ][
	print "--  Fault"
    ]
]
test-string: does [
    fmt: "<%s> <%10s>  <%-10s>  <%010s> ---"
    dta: ["a" "b" "c" "d"]
    test-base fmt dta
]

test-f: does [
    fmt: "%f %10f %-10f %4.2f %-10.3f %3.8f ---"
    dta: reduce [ pi pi pi pi pi  pi]
    test-base fmt dta
]
test-e: does [
    fmt: "%E %10e %-10E %4.2E %-10.3e %3.8E ---"
    dta: reduce [ pi pi pi pi pi  pi]
    test-base fmt dta
]

test-d: does [
    fmt: "%d  %10d  %-10d %2d^/"
    dta: reduce [ random 1000 random 1000 random 10000  3 ]
    test-base fmt dta
]

test-string
test-f
test-e
test-d


# Load EISMINT1 data
load_eismint1_moving = function(fldr)
{
    xHt1 = read.table(file.path(fldr,"EISMINT1-moving_x-H_type1.txt"),header=TRUE)
    xHt2 = read.table(file.path(fldr,"EISMINT1-moving_x-H_type2.txt"),header=TRUE)
    xHe  = read.table(file.path(fldr,"EISMINT1-moving_x-H_exactmargin.txt"),header=TRUE)

    xuxy      = read.table(file.path(fldr,"EISMINT1-moving_x-uxy_mean.txt"),header=TRUE)
    xtprime   = read.table(file.path(fldr,"EISMINT1-moving_x-T_prime_base.txt"),header=TRUE)
    tprime    = read.table(file.path(fldr,"EISMINT1-moving_divide_T_prime.txt"),header=TRUE)
    uz        = read.table(file.path(fldr,"EISMINT1-moving_divide_uz.txt"),header=TRUE)

    eis1 = list(x=seq(0,750,by=10),s=seq(0,1,by=0.05))

    # Variables versus distance from divide x
    eis1$Ht1          = approx(x=xHt1$x,y=xHt1$H,       xout=eis1$x,rule=2)$y
    eis1$Ht2          = approx(x=xHt2$x,y=xHt2$H,       xout=eis1$x,rule=2)$y
    eis1$He           = approx(x=xHe$x, y=xHe$H,        xout=eis1$x,rule=2)$y
    eis1$uxy_mean     = approx(x=xuxy$x,y=xuxy$uxy_mean,xout=eis1$x,rule=2)$y
    eis1$T_prime_base = approx(x=xtprime$x,y=xtprime$T_prime_base,xout=eis1$x,rule=2)$y

    # Variables at divide versus normalized ice thickness sigma
    eis1$T_prime      = approx(x=tprime$sigma,y=tprime$T_prime,xout=eis1$s,rule=2)$y
    eis1$uz           = approx(x=uz$sigma,    y=uz$uz,         xout=eis1$s,rule=2)$y

    return(eis1)
}

load_eismint1_fixed = function(fldr)
{
    xHt1 = read.table(file.path(fldr,"EISMINT1-fixed_x-H_type1.txt"),header=TRUE)
    xHt2 = read.table(file.path(fldr,"EISMINT1-fixed_x-H_type2.txt"),header=TRUE)

    xuxy    = read.table(file.path(fldr,"EISMINT1-fixed_x-uxy_mean_3D.txt"),header=TRUE)
    # xtprime = read.table(file.path(fldr,"EISMINT1-fixed_x-T_prime_base.txt"),header=TRUE)

    eis1 = data.frame(x=seq(0,750,by=10))
    eis1$Ht1          = approx(x=xHt1$x,y=xHt1$H,       xout=eis1$x,rule=2)$y
    eis1$Ht2          = approx(x=xHt2$x,y=xHt2$H,       xout=eis1$x,rule=2)$y
    eis1$uxy_mean     = approx(x=xuxy$x,y=xuxy$uxy_mean,xout=eis1$x,rule=2)$y
    # eis1$T_prime_base = approx(x=xtprime$x,y=xtprime$T_prime_base,xout=eis1$x,rule=2)$y

    return(eis1)
}

# Check data
if (FALSE) {

    eis1m = load_eismint1_moving("./EISMINT1-moving/")
    eis1f = load_eismint1_fixed("./EISMINT1-fixed/")

    eis1 = eis1f

    xlim = c(0,750)
    ylim = c(0,4000)

    plot(xlim,ylim,type="n",ann=FALSE,axes=FALSE)
    axis(1)
    axis(2)
    mtext(side=1,line=2.5,las=0,"Distance from divide [km]")
    mtext(side=2,line=2.5,las=0,"Ice thickness [m]")
    grid()

    lines(eis1$x,eis1$Ht1,col=1,lwd=2,lty=1)
    lines(eis1$x,eis1$Ht2,col=1,lwd=2,lty=2)
    # lines(eis1$x,eis1$He, col=1,lwd=2,lty=3)

    legend("bottomleft",inset=0.02,bty="n",col=c(1,1,1),lwd=c(2,2,2),lty=c(1,2,3),c("type I","type II","exact"))

    box()

}


model_shootnumber <- function (canopyShootNumber_t1 = 288.0,
         leafNumber = 3.34,
         sowingDensity = 288.0,
         targetFertileShoot = 600.0,
         tilleringProfile_t1 = c(288.0),
         leafTillerNumberArray_t1 = c(1, 1, 1),
         numberTillerCohort_t1 = 1){
    #'- Name: ShootNumber -Version: 1.0, -Time step: 1
    #'- Description:
    #'            * Title: CalculateShootNumber Model
    #'            * Author: Pierre MARTRE
    #'            * Reference: Modeling development phase in the
    #'                Wheat Simulation Model SiriusQuality.
    #'                See documentation at http://www1.clermont.inra.fr/siriusquality/?page_id=427
    #'            * Institution: INRA/LEPSE Montpellier
    #'            * Abstract: calculate the shoot number and update the related variables if needed
    #'- inputs:
    #'            * name: canopyShootNumber_t1
    #'                          ** description : shoot number for the whole canopy
    #'                          ** variablecategory : state
    #'                          ** datatype : DOUBLE
    #'                          ** min : 0
    #'                          ** max : 10000
    #'                          ** default : 288.0
    #'                          ** unit : shoot m-2
    #'                          ** inputtype : variable
    #'            * name: leafNumber
    #'                          ** description : Leaf number
    #'                          ** variablecategory : state
    #'                          ** inputtype : variable
    #'                          ** datatype : DOUBLE
    #'                          ** min : 0
    #'                          ** max : 10000
    #'                          ** default : 3.34
    #'                          ** unit : leaf
    #'            * name: sowingDensity
    #'                          ** description : number of plant /m²
    #'                          ** parametercategory : species
    #'                          ** datatype : DOUBLE
    #'                          ** min : 0
    #'                          ** max : 500
    #'                          ** default : 288.0
    #'                          ** unit : plant m-2
    #'                          ** inputtype : parameter
    #'            * name: targetFertileShoot
    #'                          ** description : max value of shoot number for the canopy
    #'                          ** parametercategory : species
    #'                          ** datatype : DOUBLE
    #'                          ** min : 280
    #'                          ** max : 1000
    #'                          ** default : 600.0
    #'                          ** unit : shoot
    #'                          ** inputtype : variable
    #'            * name: tilleringProfile_t1
    #'                          ** description :  store the amount of new tiller created at each time a new tiller appears
    #'                          ** variablecategory : state
    #'                          ** datatype : DOUBLELIST
    #'                          ** default : [288.0]
    #'                          ** unit :
    #'                          ** inputtype : variable
    #'            * name: leafTillerNumberArray_t1
    #'                          ** description : store the number of tiller for each leaf layer
    #'                          ** variablecategory : state
    #'                          ** datatype : INTLIST
    #'                          ** unit : leaf
    #'                          ** default : [1, 1, 1]
    #'                          ** inputtype : variable
    #'            * name: numberTillerCohort_t1
    #'                          ** description :  Number of tiller which appears
    #'                          ** variablecategory : state
    #'                          ** datatype : INT
    #'                          ** min : 0
    #'                          ** max : 10000
    #'                          ** default : 1
    #'                          ** unit :
    #'                          ** inputtype : variable
    #'- outputs:
    #'            * name: averageShootNumberPerPlant
    #'                          ** description : average shoot number per plant in the canopy
    #'                          ** variablecategory : state
    #'                          ** datatype : DOUBLE
    #'                          ** min : 0
    #'                          ** max : 10000
    #'                          ** unit : shoot m-2
    #'            * name: canopyShootNumber
    #'                          ** description : shoot number for the whole canopy
    #'                          ** variablecategory : state
    #'                          ** datatype : DOUBLE
    #'                          ** min : 0
    #'                          ** max : 10000
    #'                          ** unit : shoot m-2
    #'            * name: leafTillerNumberArray
    #'                          ** description : store the number of tiller for each leaf layer
    #'                          ** variablecategory : state
    #'                          ** datatype : INTLIST
    #'                          ** unit : leaf
    #'            * name: tilleringProfile
    #'                          ** description :  store the amount of new tiller created at each time a new tiller appears
    #'                          ** variablecategory : state
    #'                          ** datatype : DOUBLELIST
    #'                          ** unit : dimensionless
    #'            * name: numberTillerCohort
    #'                          ** description : Number of tiller which appears
    #'                          ** variablecategory : state
    #'                          ** datatype : INT
    #'                          ** min : 0
    #'                          ** max : 10000
    #'                          ** unit : dimensionless
    leafTillerNumberArray <- vector()
    tilleringProfile <- vector()
    lNumberArray_rate <- vector()
    emergedLeaves <- max(1, ceiling(leafNumber - 1.0))
    shoots <- fibonacci(emergedLeaves)
    canopyShootNumber <- min(shoots * sowingDensity, targetFertileShoot)
    averageShootNumberPerPlant <- canopyShootNumber / sowingDensity
    if (canopyShootNumber != canopyShootNumber_t1)
    {
        tilleringProfile <- c(tilleringProfile_t1, canopyShootNumber - canopyShootNumber_t1)
    }
    numberTillerCohort <- length(tilleringProfile)
    for( i in seq(length(leafTillerNumberArray_t1), ceiling(leafNumber)-1, 1)){
        lNumberArray_rate <- c(lNumberArray_rate, numberTillerCohort)
    }
    leafTillerNumberArray <- c(leafTillerNumberArray_t1, lNumberArray_rate)
    return (list ("averageShootNumberPerPlant" = averageShootNumberPerPlant,"canopyShootNumber" = canopyShootNumber,"leafTillerNumberArray" = leafTillerNumberArray,"tilleringProfile" = tilleringProfile,"numberTillerCohort" = numberTillerCohort))
}

fibonacci <- function (n){
    if (n <= 1)
    {
        return( n)
    }
    else
    {
        return( fibonacci(n - 1) + fibonacci(n - 2))
    }
}

init_shootnumber <- function (sowingDensity = 288.0,
         targetFertileShoot = 600.0){
    tilleringProfile_t1 <- vector()
    leafTillerNumberArray_t1 <- vector()
    leafTillerNumberArray <- vector()
    tilleringProfile <- vector()
    canopyShootNumber <- sowingDensity
    averageShootNumberPerPlant <- 1.0
    tilleringProfile <- c(tilleringProfile, sowingDensity)
    numberTillerCohort <- 1
    leafTillerNumberArray <- vector()
    return (list ("averageShootNumberPerPlant" = averageShootNumberPerPlant,"canopyShootNumber" = canopyShootNumber,"leafTillerNumberArray" = leafTillerNumberArray,"tilleringProfile" = tilleringProfile,"numberTillerCohort" = numberTillerCohort))
}


#' @title findMax
#' @description unknown
#' @family abysmally documented
#' @author  unknown, \email{<unknown>@@dfo-mpo.gc.ca}
#' @export
findMax <- function(x,y){
			np 	= length(x)
			ix 	= which.max(y)
			ixx = min(np-1,max(2,ix))
			tx 	= x[ixx + c(-1,0,1)]
			ty 	= y[ixx + c(-1,0,1)]
			co 	= coef(lm(ty ~ tx + I(tx^2)))
			xmax = co[2] /(-2 * co[3])
			ymax = co %*% (xmax^(0:2))
		return(c(xmax,ymax))
	}


prior <- setClass(
  Class = "prior",
  slots = list(
    data = "list",
    theta_range = "numeric",
    func = "function",
    desc = "character",
    type = "character",
    dist_type = "character",
    plot = "list",
    parameters = "list",
    function_text = "character"
  )
)

likelihood <- setClass(
  Class = "likelihood",
  slots = list(
    data = "list",
    # theta_range = "",
    func = "function",
    desc = "character",
    observation = "numeric",
    # type = "character",
    dist_type = "character",
    plot = "list",
    # parameters = "",
    marginal = "character"
  )
)

product <- setClass(
  Class = "product",
  slots = list(
    data = "list",
    desc = "character",
    K = "numeric",
    lik = "function",
    prior = "function",
    theta_range = "numeric",
    likelihood_obj = "likelihood",
    prior_obj = "prior"
  )
)

posterior <- setClass(
  Class = "posterior",
  slots = list(
    data = "list",
    desc = "character",
    K = "numeric",
    lik = "function",
    prior = "function",
    theta_range = "numeric",
    likelihood_obj = "likelihood",
    prior_obj = "prior"
  )
)

prediction <- setClass(
  Class = "prediction",
  slots = list(
    data = "list",
    desc = "character",
    K = "numeric",
    lik = "function",
    prior = "function",
    theta_range = "numeric",
    likelihood_obj = "likelihood",
    prior_obj = "prior"
  )
)

setClassUnion("bayesplay", c(
  "likelihood",
  "prior",
  "product",
  "posterior",
  "prediction"
))

setMethod(
  "show",
  "bayesplay",
  function(object) {
    cat(object@desc, "\n")
  }
)

show <- function(x) {
  UseMethod("show")
}

#' Get fields from data slot
#' @param x a \code{bayesplay} object
#' @param name field name
#' @return content of the named field from the data slot
setMethod(
  "$",
  "bayesplay",
  function(x, name) {
    returnval <- x@data[[name]]
    return(returnval)
  }
)

#' Get names from data slot
#' @param x a \code{bayesplay} object
#' @return the field names from the data slot
setMethod("names",
  signature = "bayesplay",
  function(x) {
    return(names(x@data))
  }
)

# constants
theta <- "\u03F4"
posterior_labs <- list(x = theta, y = "Density")
likelihood_labs <- list(x = theta, y = "Pr(Outcome)")

setClass(
  Class = "normal",
  list(
    family = "character",
    fun = "function",
    default_range = "numeric"
  ),
  prototype = list(
    family = "normal",
    fun = function(x, mean, sd, ...) {
      dnorm(x = mean, mean = x, sd = sd)
    },
    default_range = c(-Inf, Inf)
  )
)

setClass(
  Class = "point",
  list(
    family = "character",
    fun = "function",
    default_range = "numeric"
  ),
  prototype = list(
    family = "point",
    fun = function(x, point, ...) {
      ifelse(x == point, 1, 0)
    },
    default_range = c(-Inf, Inf)
  )
)

setClass(
  Class = "uniform",
  list(
    family = "character",
    fun = "function",
    default_range = "numeric"
  ),
  prototype = list(
    family = "uniform",
    fun = function(x, min, max, ...) {
      dunif(x = x, min = min, max = max)
    },
    default_range = c(-Inf, Inf)
  )
)

setClass(
  Class = "student_t",
  list(family = "character", fun = "function", default_range = "numeric"),
  prototype = list(
    family = "student_t",
    fun = function(x, mean, sd, df) {
      dt_scaled(x = mean, mean = x, sd = sd, df = df)
    },
    default_range = c(-Inf, Inf)
  )
)

setClass(
  Class = "cauchy",
  list(family = "character", fun = "function", default_range = "numeric"),
  prototype = list(
    family = "cauchy",
    fun = function(x, location = 0, scale) {
      dcauchy(x = x, location = location, scale = scale)
    },
    default_range = c(-Inf, Inf)
  )
)

setClass(
  Class = "beta",
  list(family = "character", fun = "function", default_range = "numeric"),
  prototype = list(
    family = "beta",
    fun = function(x, alpha, beta) {
      dbeta(x = x, shape1 = alpha, shape2 = beta)
    },
    default_range = c(0, 1)
  )
)

setClass(
  Class = "noncentral_t",
  list(family = "character", fun = "function"),
  prototype = list(
    family = "noncentral_t",
    fun = function(x, t, df) {
      suppressWarnings(dt(x = t, df = df, ncp = x))
    }
  )
)

setClass(
  Class = "noncentral_d",
  list(family = "character", fun = "function"),
  prototype = list(
    family = "noncentral_d",
    fun = function(x, d, n) {
      suppressWarnings(dt(x = d * sqrt(n), df = n - 1, ncp = x * sqrt(n)))
    }
  )
)

setClass(
  Class = "noncentral_d2",
  list(family = "character", fun = "function"),
  prototype = list(
    family = "noncentral_d2",
    fun = function(x, d, n1, n2) {
      suppressWarnings(dt(
        x = d / sqrt(1 / n1 + 1 / n2),
        df = n1 + n2 - 2,
        ncp = x * sqrt((n1 * n2) / (n1 + n2))
      ))
    }
  )
)

setClass(
  Class = "binomial",
  list(family = "character", fun = "function"),
  prototype = list(
    family = "binomial",
    fun = function(p, successes, trials) {
      dbinom(prob = p, size = trials, x = successes)
    }
  )
)

setClassUnion(
  "family",
  c(
    "normal",
    "student_t",
    "noncentral_t",
    "noncentral_d",
    "noncentral_d2",
    "binomial",
    "point",
    "uniform",
    "cauchy"
  )
)


#' crossprod
#'
#' Croddproducts.
#'
#' @details
#' If \code{y} is a numeric matrix, then \code{x} will be promoted to a numeric
#' matrix, and the return will therefore be numeric (not float).
#'
#' @param x
#' A float vector/matrix.
#' @param y
#' Either \code{NULL}, or a numeric/float matrix.
#'
#' @return
#' A float matrix (unless \code{y} is numeric; see details section).
#'
#' @examples
#' library(float)
#'
#' s = flrunif(10, 3)
#' crossprod(s)
#' tcrossprod(s)
#'
#' @useDynLib float R_crossprod_spm R_crossprod_spmspm R_tcrossprod_spm R_tcrossprod_spmspm
#' @name crossprod
#' @rdname crossprod
NULL

cp_float32 = function(x, y=NULL)
{
  if (is.float(x))
  {
    if (is.null(y))
      d = .Call(R_crossprod_spm, DATA(x))
    else if (is.float(y))
      d = .Call(R_crossprod_spmspm, DATA(x), DATA(y))
    else
      return(base::crossprod(dbl(x), y))
  }
  else if (is.matrix(x) && is.float(y))
    return(base::crossprod(x, dbl(y)))
  else
    return(base::crossprod(x, y))

  float32(d)
}

tcp_float32 = function(x, y=NULL)
{
  if (is.float(x))
  {
    if (is.null(y))
      d = .Call(R_tcrossprod_spm, DATA(x))
    else if (is.float(y))
      d = .Call(R_tcrossprod_spmspm, DATA(x), DATA(y))
    else
      return(base::tcrossprod(dbl(x), y))
  }
  else if (is.matrix(x) && is.float(y))
    return(base::tcrossprod(x, dbl(y)))
  else
    return(base::tcrossprod(x, y))

  float32(d)
}

#' @rdname crossprod
#' @export
setMethod("crossprod", signature(x="Mat", y="ANY"), cp_float32)

#' @rdname crossprod
#' @export
setMethod("tcrossprod", signature(x="Mat", y="ANY"), tcp_float32)


# Comparing pictures from literature with those made directly

# libs ----
library("Momocs")

# input ----
inNProf <- list.files("./Obr/Porovnani/Prof/", full.names = T)
inNSide <- list.files("./Obr/Porovnani/Side/", full.names = T)
inNTop <- list.files("./Obr/Porovnani/Top/", full.names = T)

inProf <- import_jpg(jpg.path = inNProf, auto.notcentered = TRUE,
                     threshold = 0.5, verbose = TRUE)

inSide <- import_jpg(jpg.path = inNSide, auto.notcentered = TRUE,
                     threshold = 0.5,verbose = TRUE)

inTop <- import_jpg(jpg.path = inNTop, auto.notcentered = TRUE,
                    threshold = 0.5, verbose = TRUE)

# fac ----
facSlot <- data.frame(factor(c(rep("Lit", 10), rep("Orig", 10))))
names(facSlot) <- "Puv"
facSlot$Nr <- factor(rep(0:9, 2))

# outlines ----
outProf <- Out(inProf, fac = facSlot)
outSide <- Out(inSide, fac = facSlot)
outTop <- Out(inTop, fac = facSlot)

panel(outProf, fac = "Puv", names = "Nr")
panel(outSide, fac = "Puv", names = "Nr")
panel(outTop, fac = "Puv", names = "Nr")

# manipulate outlines ----
manProf <- outProf %>%
  coo_slidedirection("S") %>% coo_center() %>% coo_scale() %>%
  coo_smooth(50) %>% coo_sample(200)

manSide <- outSide %>%
  coo_alignxax() %>% coo_slidedirection("W") %>% coo_center() %>%
  coo_smooth(200) %>% coo_sample(200)

manTop <- outTop %>%
  coo_alignxax() %>% coo_slidedirection("W") %>% coo_center() %>%
  coo_smooth(200) %>% coo_sample(400)

panel(manProf, fac = "Puv", names = "Nr")
panel(manTop, fac = "Puv", names = "Nr")
panel(manSide, fac = "Puv", names = "Nr")

# stack(filter(manProf, Nr == 5))
#
# stack(filter(manTop, Nr == 1))
# stack(filter(manTop, Nr == 2))
# stack(filter(manTop, Nr == 3))

# efourier ----
efProf <- efourier(manProf, nb.h = 10, norm = FALSE, smooth.it = 0,
                   start = FALSE, verbose = TRUE)

efSide <- efourier(manSide, nb.h = 11, norm = TRUE, smooth.it = 0,
                   start = FALSE, verbose = TRUE)

efTop <- efourier(manTop, nb.h = 12, norm = TRUE, smooth.it = 0,
                  start = FALSE, verbose = TRUE)

# centroid size ----
# coo_centsize(manProf)
# coo_centsize(manSide)
# coo_centsize(manTop)

# mean shapes ----
Prof <- mshapes(efProf, 1)
Side <- mshapes(efSide, 1)
Top <- mshapes(efTop, 1)

# t-test
# lit <- filter(manProf, Puv == "Lit")
# orig <- filter(manProf, Puv == "Orig")
#
# t.test(Prof$shp$Lit, Prof$shp$Orig)
# t.test(Prof$shp$Lit, Prof$shp$Orig, paired = T)
#
# t.test(lit$coo$LitProf0, orig$coo$OrigProf0)

# stack plots of meanshapes ----
# pdf(file = "./Obr/prof.pdf")
# LitProf <- Prof$shp$Lit    %T>% coo_plot(border="blue")
# KreProf <- Prof$shp$Orig  %T>% coo_draw(border="red")
# dev.off()
#
# pdf(file = "./Obr/side.pdf")
# LitSide <- Side$shp$Lit    %T>% coo_plot(border="blue")
# KreSide <- Side$shp$Orig  %T>% coo_draw(border="red")
# dev.off()
#
# pdf(file = "./Obr/top.pdf")
# LitTop <- Top$shp$Lit    %T>% coo_plot(border="blue")
# KreTop <- Top$shp$Orig  %T>% coo_draw(border="red")
# dev.off()

# difference plots of meanshapes ----
pdf(file = "./Obr/panProf.pdf")
efProf %>% mshapes("Puv") %>% plot_mshapes(col2="#0000FF")
dev.off()

pdf(file = "./Obr/panSide.pdf")
efSide %>% mshapes("Puv") %>% plot_mshapes(col2="#0000FF")
dev.off()

pdf(file = "./Obr/panTop.pdf")
efTop %>% mshapes("Puv") %>% plot_mshapes(col2="#0000FF")
dev.off()

# tps plots ----
pdf(file = "./Obr/isoProf.pdf", width = 10, height = 10)
tps_iso(LitProf, KreProf, cont.col = "gray40", grid = F,
        shp.border = c("black", "blue"), shp.lwd = c(4, 3), shp.lty = c(3, 3),
        legend.text = c("Lit", "Orig"))
dev.off()

pdf(file = "./Obr/isoSide.pdf", width = 9, height = 3)
tps_iso(LitSide, KreSide, cont.col = "gray40", grid = F,
        shp.border = c("black", "blue"), shp.lwd = c(4, 3), shp.lty = c(3, 3),
        legend.text = c("Lit", "Orig"))
dev.off()

pdf(file = "./Obr/isoTop.pdf", width = 11, height = 4)
tps_iso(LitTop, KreTop, cont.col = "gray40", grid = F,
        shp.border = c("black", "blue"), shp.lwd = c(4, 3), shp.lty = c(3, 3),
        legend.text = c("Lit", "Orig"))
dev.off()

# indiv.
tps_iso(manProf$coo$LitProf1, manProf$coo$OrigProf1)

coo_lolli(LitProf, KreProf)
coo_lolli(LitSide, KreSide)
coo_lolli(LitTop, KreTop)
# or?
coo_arrows(LitProf, KreProf)
coo_arrows(LitSide, KreSide)
coo_arrows(LitTop, KreTop)

# coo_plot(LitProf)
# coo_ruban(LitProf, edm(LitProf, KreProf), lwd=8)
# coo_ruban(LitTop, edm(LitTop, KreTop), lwd=8)

# a <- efourier(manTop)
# ms.Top <- mshapes(a, fac = "Puv", nb.pts = 80)$shp
# fr <- ms.Top$Lit
# to <- ms.Top$Orig
# tps_iso(fr, to)

# end
rm(list = ls())
graphics.off()


#' @title midg is an abalone tagging data-set from the Actaeons
#'
#' @description midg is a tagging data-set for blacklip abalone
#'     (\emph{Haliotis rubra}) from the middle ground in the Actaeons
#'     in Tasmania's Block 13. All individuals were recaptured in 2003,
#'     the site number was 478, at Latitude -43.54 longitude 146.99,
#'     and there are 347 observations. All Dt = 1 year.
#'
#' @name midg
#'
#' @docType data
#'
#' @format A data.frame of abalone tagging data
#' \describe{
#'   \item{RecapL}{the length at recapture}
#'   \item{Lt}{the length at tagging}
#'   \item{Dt}{The time interval between tagging and recapture, in this
#'       instance they are all listed as 1 year}
#'   \item{DL}{the growth increment in mm}
#' }
#'
#' @section Subjects:
#'  \itemize{
#'    \item growth curves
#'    \item inverse logistic, von Bertalanffy, Gompertz
#'    \item Static model fitting
#'  }
#'
#' @source Thanks to the Institute of Marine and Antarctic Science,
#'     which is part of the University of Tasmania, and especially to
#'     Dr Craig Mundy, leader of the Abalone Group, for permission to use
#'     this data collected in 2003.
#'
#' @examples
#'  data(midg)
#'  head(midg,20)
#'  oldpar <- par(no.readonly=TRUE)
#'  plot(midg$Lt,midg$DL,type="p",pch=16,cex=1.0,xlim=c(5,180))
#'  abline(h=0,col=1)
#'  par(oldpar)
NULL

#' @title tasab is a matrix of abalone maturity-at-length data
#'
#' @description tasab is a 715 x 4 matrix of maturity-at-length data
#'     for blacklip abalone (\emph{Haliotis rubra}) from two sites
#'     along the Tasmanian west coast. All data was collected in
#'     February 1995, but details, such as site name, accurate
#'     location, statistical block, year, month, and other
#'     details have been omitted for brevity.
#'
#' @name tasab
#'
#' @docType data
#'
#' @format A data.frame of maturity-at-length data
#' \describe{
#'   \item{site}{an identifier for the two different sites sampled}
#'   \item{sex}{I = immature, M = male, F = female}
#'   \item{length}{the shell length in mm}
#'   \item{mature}{was the animal mature = 1 or not = 0}
#' }
#'
#' @section Subjects:
#'  \itemize{
#'    \item maturity ogives or logistic curves
#'    \item Binomial likelihoods
#'  }
#'
#' @source Thanks to the Institute of Marine and Antarctic Science,
#'     which is part of the University of Tasmania, and especially to
#'     Dr Craig Mundy, leader of the Abalone Group, for permission to use
#'     this data collected in February 1995.
#'
#' @examples
#'  data(tasab)
#'  head(tasab,20)
#'  table(tasab$site,tasab$sex)
NULL


score <- function(input) {
    var0 <- exp(subroutine0(input))
    var1 <- exp(subroutine1(input))
    var2 <- exp(subroutine2(input))
    var3 <- ((var0) + (var1)) + (var2)
    return(c((var0) / (var3), (var1) / (var3), (var2) / (var3)))
}
subroutine0 <- function(input) {
    return(((0) + (subroutine3(input))) + (subroutine4(input)))
}
subroutine1 <- function(input) {
    return(((0) + (subroutine5(input))) + (subroutine6(input)))
}
subroutine2 <- function(input) {
    return(((0) + (subroutine7(input))) + (subroutine8(input)))
}
subroutine3 <- function(input) {
    if ((input[3]) > (3.1500000000000004)) {
        var0 <- -1.1736122903444903
    } else {
        if ((input[2]) > (3.35)) {
            var0 <- -0.9486122853153485
        } else {
            var0 <- -0.9598622855668056
        }
    }
    return(var0)
}
subroutine4 <- function(input) {
    if ((input[3]) > (3.1500000000000004)) {
        if ((input[3]) > (4.450000000000001)) {
            var0 <- -0.07218200074594171
        } else {
            var0 <- -0.0725391787456957
        }
    } else {
        if ((input[2]) > (3.35)) {
            var0 <- 0.130416969124648
        } else {
            var0 <- 0.12058330491181404
        }
    }
    return(var0)
}
subroutine5 <- function(input) {
    if ((input[3]) > (1.8)) {
        if ((input[4]) > (1.6500000000000001)) {
            var0 <- -1.1840003561812273
        } else {
            var0 <- -0.99234128317334
        }
    } else {
        var0 <- -1.1934739985732523
    }
    return(var0)
}
subroutine6 <- function(input) {
    if ((input[4]) > (0.45000000000000007)) {
        if ((input[4]) > (1.6500000000000001)) {
            var0 <- -0.06203313079859976
        } else {
            var0 <- 0.11141505233015861
        }
    } else {
        if ((input[3]) > (1.4500000000000002)) {
            var0 <- -0.0720353255122301
        } else {
            var0 <- -0.07164473223425313
        }
    }
    return(var0)
}
subroutine7 <- function(input) {
    if ((input[4]) > (1.6500000000000001)) {
        if ((input[3]) > (5.3500000000000005)) {
            var0 <- -0.9314095846701695
        } else {
            var0 <- -0.9536869036452162
        }
    } else {
        if ((input[3]) > (4.450000000000001)) {
            var0 <- -1.115439610985773
        } else {
            var0 <- -1.1541827744206368
        }
    }
    return(var0)
}
subroutine8 <- function(input) {
    if ((input[3]) > (4.750000000000001)) {
        if ((input[3]) > (5.150000000000001)) {
            var0 <- 0.12968922424213622
        } else {
            var0 <- 0.07468384042736965
        }
    } else {
        if ((input[2]) > (2.7500000000000004)) {
            var0 <- -0.07311533184609437
        } else {
            var0 <- -0.06204412771870974
        }
    }
    return(var0)
}


# -*- coding: utf-8 -*-
"""ar_hw6.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/18rtZgaq0UI96qYguCIX8fQ6apMYKxQ8W

# Práctico 6 - Modelos de grafos

# 1). Ambientes de trabajo

## 1.a) Ambiente COLAB remoto

1.   Abrir en navegador: https://colab.research.google.com/
2.   Abrir el notebook de la tarea:
     File-> Open Notebook -> Github -> https://github.com/prbocca/na101_master -> homework_6_models
3.   Guardar el notebook en su Google Drive:
     File -> Save a Copy in Drive...
4.   Renombrar el archivo `"cedula ID"_ar_hw6.ipynb`, por ejemplo *33484022_ar_hw6.ipynb*
5.   Al final usted deberá descargar el notebook. Asegurarse que se están guardando las salidas de ejecución en el notebook: File -> Download .ipynb
6.   Luego estos archivos deberán ser enviados a prbocca@fing.edu.uy

##1.b) Ambiente RSTUDIO local (opcional)

Abrir el .r de la tarea en: https://github.com/prbocca/na101_master/tree/master/homework_6_models

## 1.c) Cargar Librerias

Todas las librerías deben instalarse correctamente, si el proceso se interrumpe o alguna librería da error en la instalación, entonces habrá problemas en el código más adelante. Si tiene este tipo de problemas pruebe hacer `Runtime -> Factory reset runtime`, y volver a intentar.
"""

# cargar librerias
load_libs <- function(libraries = libs, install=TRUE){
  if (install){ # instalar librerias no instaladas
    new.packages <- libs[!(libs %in% installed.packages()[,"Package"])]
    if(length(new.packages)) install.packages(new.packages)
  }
  #cargo librerias
  for (lib in libraries){
    require(lib, character.only=TRUE, quietly = FALSE)
  }
}

libs = c("sand","igraph")

load_libs(libs)

"""## 1.d) Descargar funciones auxiliares"""

#directorio donde se va a trabajar
data_path = "/content/ar/hw6/"

dir.create(data_path, showWarnings = FALSE, recursive = TRUE)
setwd(data_path)
getwd()
list.files()

# cargo funciones auxiliares
source("https://raw.githubusercontent.com/prbocca/na101_master/master/homeworks_common.r")

"""# 2). Modelos clásicos de grafos en `R`

Seguir las Secciones 5.1 y 5.2 del libro [SANDR], ejecutando el código fuente incluido.
"""

#5.1 Introduction
#5.2 Classical Random Graph Models

#The function erdos.renyi.game in igraph can be used to simulate classical
#random graphs of either type. Figure 5.1 shows a realization of a classical random
#graph, based on the choice of N v = 100 vertices and a probability of p = 0.02 of an
#edge between any pair of vertices. Using a circular layout, we can see that the edges
#appear to be scattered between vertex pairs in a fairly uniform manner, as expected.
set.seed(42)
g.er <- erdos.renyi.game(100, 0.02)
plot(g.er, layout=layout.circle, vertex.label=NA)

# Note that random graphs generated in the manner described above need not be connected.
is.connected(g.er)
#2 [1] FALSE

#Although this particular realization is not connected, it does nevertheless have a
# giant component, containing 71 of the 100 vertices. All other components contain
#between one and four vertices only.
table(sapply(decompose.graph(g.er), vcount))
# 3 1 2 3 4 71
#4 15 2 2 1 1
#In general, a classical random graph G will with high probability have a giant com-
#ponent if p = c/N v for some c > 1.

# Under this same parameterization for p, for c > 0, the degree distribution will
# be well-approximated by a Poisson distribution, with mean c, for large N v .
# Indeed, in our simulated random graph, the mean degree is quite close to the
# expected value of (100 − 1) × 0.02 = 1.98.
mean(degree(g.er))

# Furthermore, we see that the degree distribution is quite homogeneous.
hist(degree(g.er), col="lightblue", xlab="Degree", ylab="Frequency", main="")

#Other properties of classical random graphs include that there are relatively few
#vertices on shortest paths between vertex pairs72
average.path.length(g.er)
#[1] 5.276511
diameter(g.er)
#[1] 14
#and that there is low clustering.
transitivity(g.er)
#[1] 0.01639344
# More specifically, under the conditions above, it can be shown that the diameter
# varies like O(log N v ), and the clustering coefficient, like N v −1.

"""# 3). Distribución de grado de Erdös-Renyi, $G(n, p)$ , en `R`.

Utilizando la función `erdos.renyi.game()` generar grafos aleatorios de distinto orden.

## 3.a) Crecer la cantidad de vértices

Si fijamos $p = 0.02$, al crecer la cantidad de vértices:
¿qué sucede con el grado promedio?, y
¿la distribución de grado se acerca a una Normal o a una Poisson?

Verificar comparando el histograma con la distribución teórica para $n \in \{10, 100, 1000, 10000\}$.
"""

# Gnp: efecto de crecer la red, se aproxima a una normal
par(mfrow=c(3,2))
p=0.02
for (i in 1:5){
  n = 10^i
  g.er <- erdos.renyi.game(n, p.or.m=p, type="gnp")
  #hist(degree(g.er), probability = T, col="lightblue", xlab="Degree", ylab="Probabilities", main="")
  g.er.dd = degree_distribution(g.er)
  plot(g.er.dd, xlab="Degree", ylab="Probabilities", main=paste("n=",n))
  x = seq(from=1,to=length(g.er.dd), by=1)
  lines(x, dnorm(x, mean = n*p, sd = sqrt(n*p*(1-p))), type="l",col="red")
  print(paste("n =",n,", grado promedio =", mean(degree(g.er))))
}

par(mfrow=c(1,1))

"""## 3.b) Crecer la cantidad de vértices y obtener una distribución de Poisson

¿Cómo debemos cambiar el parámetro $p$ del modelo al crecer $n$ para que la  distribución tienda a una Poisson?

Verificar comparando el histograma con la distribución de Poisson para $n \in \{10, 100, 1000, 10000\}$ y un grado promedio de $1.8$.

Nota: Los parámtros de la distribución teórica fueron vistos en las clases teóricas.
"""

##################################################################
#                       TU CÓDIGO ACÁ
# Tip: similar a 3.a), los parámtros de la distribución teórica fueron vistos en las clases teóricas.
#
#
#
##################################################################

"""# 4). Otros modelos de grafos en `R`.

Seguir las Secciones 5.3 y 5.4 del libro [SANDR], ejecutando el código fuente incluido. En ellas se explican los modelos de configuración, acoplamiento preferencial, Barabási-Albert, y mundo pequeño.
"""

# 5.3 Generalized Random Graph Models

set.seed(42)

# The igraph function degree.sequence.game can be used to uniformly
# sample random graphs with fixed degree sequence. Suppose, for example, that we
# are interested in graphs of N v = 8 vertices, half of which have degree d = 2, and the
# other half, degree d = 3. Two examples of such graphs, drawn uniformly from the
# collection of all such graphs, are shown in Fig. 5.2.
degs <- c(2,2,2,2,3,3,3,3)
g1 <- degree.sequence.game(degs, method="vl")
g2 <- degree.sequence.game(degs, method="vl")
plot(g1, vertex.label=NA)
plot(g2, vertex.label=NA)

#Note that these two graphs do indeed differ, in that they are not isomorphic.
graph.isomorphic(g1, g2)
#[1] FALSE

# For a fixed number of vertices N v , the collection of random graphs with fixed
# degree sequence all have the same number of edges N e , due to the relation d  ̄ =
# 2N e /N v , where d  ̄ is the mean degree of the sequence (d (1) , . . . , d (N v ) ).
c(ecount(g1), ecount(g2))
#[1] 10 10

# On the other hand, it is important to keep in mind that all other characteristics
# are free to vary to the extent allowed by the chosen degree sequence. For example,
# we can generate a graph with the same degree sequence as our network of protein–
# protein interactions in yeast.
data(yeast)
degs <- degree(yeast)
fake.yeast <- degree.sequence.game(degs, method=c("vl"))
all(degree(yeast) == degree(fake.yeast))
# [1] TRUE

#But the original network has twice the diameter of the simulated version
diameter(yeast)
# [1] 15
diameter(fake.yeast)
# [1] 8

# and virtually all of the substantial amount of clustering originally present is now gone.
transitivity(yeast)
#[1] 0.4686178
transitivity(fake.yeast)
#[1] 0.0396504

# 5.4 Network Graph Models Based on Mechanisms

set.seed(42)

# 5.4.1 Small-World Models
# Work on modeling of this type received a good deal of its impetus from the seminal
# paper of Watts and Strogatz [146] and the ‘small-world’ network model introduced
# therein. These authors were intrigued by the fact that many networks in the real
# world display high levels of clustering, but small distances between most nodes.
#
# In order to create a network graph with both of these properties, Watts and Strogatz
# suggested instead beginning with a graph with lattice structure, and then randomly
# ‘rewiring’ a small percentage of the edges. More specifically, in this model
# we begin with a set of N v vertices, arranged in a periodic fashion, and join each
# vertex to r of its neighbors to each side. Then, for each edge, independently and
# with probability p, one end of that edge will be moved to be incident to another
# vertex, where that new vertex is chosen uniformly, but with attention to avoid the
# construction of loops and multi-edges.
# An example of a small-world network graph of this sort can be generated in
# igraph using the function watts.strogatz.game.

g.ws <- watts.strogatz.game(1, 25, 5, 0.05)
plot(g.ws, layout=layout.circle, vertex.label=NA)

# For the lattice alone, which we generate by setting p = 0, there is a substantial amount of clustering.
g.lat100 <- watts.strogatz.game(1, 100, 5, 0)
plot(g.lat100, layout=layout.circle, vertex.label=NA)
transitivity(g.lat100)
#[1] 0.6666667
#But the distance between vertices is non-trivial.
diameter(g.lat100)
#[1] 10
average.path.length(g.lat100)
#[1] 5.454545

#The effect of rewiring a relatively small number of edges in a random fashion is to
# noticeably reduce the distance between vertices, while still maintaining a similarly
# high level of clustering.
g.ws100 <- watts.strogatz.game(1, 100, 5, 0.05)
plot(g.ws100, layout=layout.circle, vertex.label=NA)
diameter(g.ws100)
#[1] 5
average.path.length(g.ws100)
#[1] 2.793939393
transitivity(g.ws100)
#[1] 0.5121305

# This effect may be achieved even with very small p. To illustrate, we simulate ac-
# cording to a particular Watts-Strogatz small-world network model, with N v = 1, 000
#and r = 10, and re-wiring probability p, as p varies over a broad range.
steps <- seq(-4, -0.5, 0.1)
len <- length(steps)
cl <- numeric(len)
apl <- numeric(len)
ntrials <- 100
for (i in (1:len)) {
  cltemp <- numeric(ntrials)
  apltemp <- numeric(ntrials)
  for (j in (1:ntrials)) {
    g <- watts.strogatz.game(1, 1000, 10, 1^steps[i])
    cltemp[j] <- transitivity(g)
    apltemp[j] <- average.path.length(g)
  }
  cl[i] <- mean(cltemp)
  apl[i] <- mean(apltemp)
}
# The results shown in Fig. 5.4, where approximate expected values for normalized
# versions of average path length and clustering coefficient are plotted, indicate that
# over a substantial range of p the network exhibits small average distance while main-
# taining a high level of clustering.
plot(steps, cl/max(cl), ylim=c(0, 1), lwd=3, type="l", col="blue", xlab=expression(log[10](p)),
  ylab="Clustering and Average Path Length")
lines(steps, apl/max(apl), lwd=3, col="red")

# 5.4.2 Preferential Attachment Models

# Many networks grow or otherwise evolve in time. The World Wide Web and
# scientific citation networks are two obvious examples. Similarly, many biological
# networks may be viewed as evolving as well, over appropriately defined time scales.
# Much energy has been invested in the development of models that mimic network growth.
# In this arena, typically a simple mechanism(s) is specified for how the network
# changes at any given point in time, based on concepts like vertex preference, fitness,
# copying, age, and the like. A celebrated example of such a mechanism is that of
# preferential attachment, designed to embody the principle that ‘the rich get richer.’
# ...

# Using the igraph function barabasi.game, we can simulate a BA random
# graph of, for example, N v = 100 vertices, with m = 1 new edges added for each new vertex.
set.seed(42)
g.ba <- barabasi.game(100, directed=FALSE)
# A visualization of this graph is shown in Fig. 5.5.
plot(g.ba, layout=layout.circle, vertex.label=NA)

# Note that the edges are spread among vertex pairs in a decidedly less uniform man-
# ner than in the classical random graph we saw in Fig. 5.1. And, in fact, there appear
# to be vertices of especially high degree—so-called ‘hub’ vertices.
# Examination of the degree distribution (also shown in Fig. 5.5)
hist(degree(g.ba), col="lightblue", xlab="Degree", ylab="Frequency", main="")
# confirms this suspicion, and indicates, moreover, that the overall distribution is quite
# heterogeneous. Actually, the vast majority of vertices have degree no more than two
# in this graph, while, on the other hand, one vertex has a degree of 11.
summary(degree(g.ba))
#Min. 1st Qu. Median Mean 3rd Qu. Max.
#1.00 1.00 1.00 1.98 2.00 11.00

# On the other hand, network graphs generated according to the BA model will
# share with their classical counterparts the tendency towards relatively few vertices
# on shortest paths between vertex pairs
average.path.length(g.ba)
# [1] 5.81555555555556
diameter(g.ba)
# [1] 12
#and low clustering.
transitivity(g.ba)
# [1] 0

"""# 5). Distribución de grado de Barabási-Albert en `R`.

Verificar que el modelo de Barabasi-Albert tiende a una distribución power-law de parámetro $\alpha = 3$ al crecer $n$.
Para esto graficar la función de distribución acumulada complementaria (CCDF) en conjunto con la recta teórica de la power-law. Usar los $n \in \{10, 100, 1000, 10000, 100000, 1000000\}$.
Para cada caso, encontrar el $\hat{\alpha}$ usando la función de ajuste de igraph, llamada `power.law.fit()`.
Además entender el test de hipótesis que se realiza en el ajuste, e interpretar el p-value del resultado.
"""

# BA: efecto de crecer la red
set.seed(42)
par(mfrow=c(3,2))

for (i in 1:6){
  n = 10^i
  g.ba = barabasi.game(n)

  # Degree distribution is the cumulative frequency of nodes with a given degree
  # this, like degree() can be specified as "in", "out", or "all"
  g.ba.dd = degree.distribution(g.ba, cumulative=T,mode="all")
  g.ba.d = degree(g.ba,v=V(g.ba),mode="all")

  # Using the power.law.fit() function I can fit a power law to the degree distribution
  # Plot degree distribution histogram, and theoretical line
  g.ba.power = NA
  ##################################################################
  #                       TU CÓDIGO ACÁ
  #
  #
  #
  ##################################################################
  print(paste("n =",n,", alpha =", g.ba.power$alpha, ", xmin =", g.ba.power$xmin))
}

"""# 6) Distribución de grado de una red real.

Mark Newman en 2006 creó un grafo de routers en Internet, con 22963 vértices y 48436 aristas.
Descargar el grafo en formato GML desde:
https://github.com/prbocca/na101_master/raw/master/homework_6_models/internet_routers-22july06.gml.zip

## 6.a) Descargar los datos

Descargar los datos en formato `GML` en el siguiente link:
https://github.com/prbocca/na101_master/raw/master/homework_6_models/internet_routers-22july06.gml.zip.

Cargar los datos en `R`.
"""

# download data
download.file(url="https://github.com/prbocca/na101_master/raw/master/homework_6_models/internet_routers-22july06.gml.zip", destfile="internet_routers-22july06.gml.zip", mode="wb")
unzip(zipfile="internet_routers-22july06.gml.zip")
list.files()

# cargar datos
g.real = NA
##################################################################
#                       TU CÓDIGO ACÁ
# Tip: usar funciones de igraph
#
#
#
##################################################################
summary(g.real)

"""## 6.b) (Opcional) Visualizar el grafo en Gephi

Visualizar los vértices de mayor grado con mayor tamaño,
y los vértices con mayor PageRank más oscuros.

El resultado debe ser similar al de la siguiente Figura: ![alt text](https://github.com/prbocca/na101_master/raw/master/homework_6_models/routers_gephi.png)

## 6.c) En `R`, graficar la distribución de grado.

También graficar con ejes log-log para una mejor visualización.
"""

# graficar distribución de grado de g.real
##################################################################
#                       TU CÓDIGO ACÁ
# Tip: usar funciones de igraph
#
#
#
##################################################################

"""## 6.d) Graficar la función de distribución acumulada complementaria (CCDF)."""

# graficar CCDF de g.real
##################################################################
#                       TU CÓDIGO ACÁ
# Tip: usar funciones de igraph
#
#
#
##################################################################

"""## 6.e) Austar una distribución Power-law

Ajustar la distribución a una power-law.

¿Cuál es el $\hat{\alpha}$ y el $d_{min}$ del ajuste?

¿Cómo interpretar el $p-value$ del test de hipotesis del resultado del ajuste?

Verificar las conclusiones comparando la CCDF con la recta ajustada. La gráfica debería ser similar a la siguiente: ![alt text](https://github.com/prbocca/na101_master/raw/master/homework_6_models/routers_powerlaw.png)
"""

# graficar la CCDF de g.real, y la distribución power-low ajustada
g.real.power = NA
##################################################################
#                       TU CÓDIGO ACÁ
# Tip: usar funciones de igraph
#
#
#
##################################################################
print(paste("El alpha estimado es =",g.real.power$alpha))


#' kmh2mph
#'
#' Conversion kilometer per hour to mile per hour.
#'
#' @param numeric  kmh Speed in Kilometer per hour.
#' @return
#'
#'
#' @author  Istituto di Biometeorologia Firenze Italy  Alfonso Crisci \email{a.crisci@@ibimet.cnr.it}
#' @keywords  kmh2mph
#'
#' @export
#'
#'
#'
#'

kmh2mph<-function(kmh)
{
  return (kmh * 0.621371);
}


ivfastplm.core <- function(y = NULL, ## outcome vector
                         x = NULL, ## regressor matrix
                         z = NULL, ## exogenous variables matrix
                         ind = NULL, ## indicator matrix
                         se = 0,
                         robust = FALSE,
                         cl = NULL,
                         sfe.index = NULL, ## index for simple fe , a vector of integer
                         cfe.index = NULL, ## index for complex fe, a list of double, e.g. c(effect, influence)
                         core.num = 1,
                         df.use = NULL,
                         df.cl.use = NULL,
                         need.fe = FALSE,
                         iv.test = FALSE,
                         first = TRUE,
                         orthog = NULL,
                         endog = NULL) {

    if(is.null(z)){
        stop("No exogenous variables.\n")
    }

    if(is.null(x)){
        stop("No regressors.\n")
    }

    data.reduce <- cbind(y, z)
    data <- cbind(y, x)

    ## create indicators
    inds <- create.indicators(ind) ## an indicator class object

    ## ------ fe ------- ##
    fe <- cfes <- sub.cfe.index <- num.cfe.index <- NULL

    ## create complex fe
    gcfe <- function(i) {
        sub.cfe.index <- cfe.index[[i]]
        inf.weight <- as.numeric(inds$levels[[sub.cfe.index[2]]])
        cfe.sub <- create.complex.effect(inds, sub.cfe.index[1],
                                         sub.cfe.index[2], t(as.matrix(inf.weight)))
        return(cfe.sub)
    }

    ## complex fe
    if (!is.null(cfe.index)) {
        ## length
        cfe.length <- length(cfe.index)
        cfes <- lapply(1:cfe.length, gcfe)
    }

    ## create an fe class object
    fe <- create.fixed.effects(inds, sfes = sfe.index, cfes = cfes)

    ## demean all variables and then recover the fixed effects in ivregression using the coefficients
    model <- SolveFixedEffects(data, fe$ptr, core.num)
    model <- name.fe.model(model, inds, fe)
    model$inds <- inds
    model$fe <- fe

    model.reduce <- SolveFixedEffects(data.reduce, fe$ptr, core.num)
    model.reduce <- name.fe.model(model.reduce, inds, fe)
    model.reduce$inds <- inds
    model.reduce$fe <- fe

    dy <- model$demeaned$y
    dz <- model.reduce$demeaned$x
    dx <- model$demeaned$x
    colnames(dy) <- colnames(y)
    colnames(dz) <- colnames(z)
    colnames(dx) <- colnames(x)

    #inv.x <- solve(t(dx)%*%dx)
    #inv.z <- solve(t(dz)%*%dz)
    #Pz <- dz%*%inv.z%*%t(dz)
    #inv.xPzx <- solve(t(dx)%*%Pz%*%dx)
    #inv.z.zx <- inv.z%*%t(dz)%*%dx
    #iv.coef <- matrix(inv.xPzx%*%t(dx)%*%Pz%*%dy,ncol=1)
    #u.hat <- matrix(dy-dx%*%iv.coef,ncol=1)

    iv.solve <- try(solveiv(Y=dy,X=dx,Z=dz),silent = T)
    if ('try-error' %in% class(iv.solve)) {
        stop("Exact collinearity in the regression.\n")
    }
    inv.x <- iv.solve[["invxx"]]
    inv.z <- iv.solve[["invzz"]]
    inv.xPzx <- iv.solve[["invXPzX"]]
    iv.coef <- iv.solve[["coef"]]
    inv.z.zx <- iv.solve[["invzzx"]]
    rownames(iv.coef) <- colnames(x)
    u.hat <- iv.solve[["residual"]]
    ZY <- iv.solve[["ZY"]]; #t(Z)*y
    XZ <- iv.solve[["XZ"]]; #t(X)*Z

    if(sum(is.na(inv.x))>0){
        stop("Exact collinearity in the regression.")
    }
    if(sum(is.na(inv.z))>0){
        stop("Exact collinearity in the regression.")
    }

    colnames(inv.xPzx) <- rownames(inv.xPzx) <- colnames(inv.x) <- rownames(inv.x) <- colnames(dx)
    colnames(inv.z) <- rownames(inv.z) <- colnames(dz)
    rownames(XZ) <- colnames(dx)
    colnames(XZ) <- colnames(dz)

    colnames(ZY) <- colnames(dy)
    rownames(ZY) <- colnames(dz)

    model.iv <- list(coefficients=iv.coef,res=u.hat)
    model.iv$fe <- fe
    if(se == 1){
        if(is.null(df.use)){
            dof.output <- get.dof(model=model,
                                  x=x,
                                  cl=NULL,
                                  ind=ind,
                                  sfe.index=sfe.index,
                                  cfe.index=cfe.index)
            gtot <- dof.output$gtot
            model.iv$dof <- dof.output$dof
            ## degree of freedom
            df <- dim(dy)[1] - gtot
        }else{
            df <- df.use
        }
        model.iv$df.original <- df
        model$df.original <- df

        if(is.null(cl)){

            sigma2 <- t(u.hat)%*%u.hat/(df)
            RMSE <- sqrt(sigma2)
            R2 <- 1 - sum(t(u.hat)%*%u.hat)/sum((data[, 1] - mean(data[, 1]))^2)
            Adj_R2 <- 1 - (1 - R2) * (dim(x)[1] - 1) / df
            projR2 <- 1 - sum(t(u.hat)%*%u.hat)/sum((c(model$demeaned$y) - mean(model$demeaned$y))^2)
            projAdj_R2 <- 1 - (1 - projR2) * (dim(x)[1] - 1) / df

            if (robust == FALSE) {
                vcov <- as.matrix(c(t(u.hat)%*%u.hat/(df))*inv.xPzx)
                stderror <- as.matrix(sqrt(diag(vcov)))
            } else{
                meat <- dz * matrix(rep(c(u.hat), dim(dz)[2]), dim(dz)[1], dim(dz)[2])
                meat <- t(meat) %*% meat
                vcov <- inv.xPzx%*%(t(inv.z.zx)%*%meat%*%inv.z.zx)%*%inv.xPzx
                vcov <- dim(dx)[1] / df*vcov
                stderror <- as.matrix(sqrt(diag(vcov)))
            }

            Tx <- c(model.iv$coefficients)/c(stderror)

            P_t <- NULL
            for (i in 1:length(Tx)) {
                subt <- pt(Tx[i], df)
                P_t <- c(P_t, 2 * min(1 - subt, subt))
            }
            CI <- cbind(c(model.iv$coefficients) - qt(0.975,df=df)*c(stderror), c(model.iv$coefficients) + qt(0.975,df=df)*c(stderror))
            model.iv$df.residual <- df

            ## F test
            if (robust == FALSE) {
                ## full model
                ##fF <- R2/(1 - R2) * df/(dim(x)[1] - df - 1)
                ## projection model
                projF <- t(model.iv$coefficients) %*% solve(vcov) %*% model.iv$coefficients/dim(x)[2]

                ##F_statistic <- cbind(fF, dim(x)[1] - df - 1, df, 1 - pf(fF, dim(x)[1] - df - 1, df))
                proj_F_statistic <- cbind(projF, dim(x)[2], df, 1 - pf(projF, dim(x)[2], df))

                ##colnames(F_statistic) <- c("F_statistic", "df1", "df2", "P value")
                colnames(proj_F_statistic) <- c("F_statistic", "df1", "df2", "P value")

                ##model.iv$F_statistic <- F_statistic
                model.iv$proj_F_statistic <- proj_F_statistic
            } else {
                ## robust wald test
                fF <- t(model.iv$coefficients) %*% solve(vcov) %*% model.iv$coefficients
                fF <- c(fF) / dim(x)[2]
                F_statistic <- cbind(fF, dim(x)[2], df, 1 - pf(fF, dim(x)[2], df))
                colnames(F_statistic) <- c("F_statistic", "df1", "df2", "P value")
                model.iv$proj_F_statistic <- F_statistic
            }

            est.coefficients <- cbind(model.iv$coefficients, stderror, Tx, P_t, CI)
            colnames(est.coefficients) <- c("Coef", "Std. Error", "t value", "Pr(>|t|)", "CI_lower", "CI_upper")
            rownames(est.coefficients) <- colnames(x)
            model.iv$est.coefficients <- est.coefficients
        }else{
            #clusted fe
            model.iv$cl <- cl
            if (dim(cl)[2] == 1) {
                stderror <- iv.cluster.se(cl = cl, x = x, u.hat = u.hat, dz=dz,
                                          sfe.index = sfe.index,
                                          cfe.index = cfe.index,
                                          ind = ind, df = df, df.cl = df.cl.use,
                                          model = model,
                                          inv.z.zx = inv.z.zx,
                                          inv.xPzx = inv.xPzx
                                          )
                num.cl <- stderror$num.cl
                vcov <- stderror$vcov.cl
                df.cl <- stderror$df.cl
                dof <- stderror$dof
                stderror <- stderror$stderror
                model.iv$dof <- dof
            }
            else if (dim(cl)[2] == 2) {

                stderror1 <- iv.cluster.se(cl = as.matrix(cl[,1]), x = x, u.hat = u.hat, dz=dz,
                                           sfe.index = sfe.index,
                                           cfe.index = cfe.index,
                                           ind = ind, df = df, df.cl = df.cl.use[1],
                                           model = model,
                                           inv.z.zx = inv.z.zx,
                                           inv.xPzx = inv.xPzx)
                num.cl1 <- stderror1$num.cl
                vcov1 <- stderror1$vcov.cl
                df.cl1 <- stderror1$df.cl
                dof1 <- stderror1$dof
                stderror1 <- stderror1$stderror

                stderror2 <-  iv.cluster.se(cl = as.matrix(cl[,2]), x = x, u.hat = u.hat, dz=dz,
                                            sfe.index = sfe.index,
                                            cfe.index = cfe.index,
                                            ind = ind, df = df, df.cl = df.cl.use[2],
                                            model = model,
                                            inv.z.zx = inv.z.zx,
                                            inv.xPzx = inv.xPzx)
                num.cl2 <- stderror2$num.cl
                vcov2 <- stderror2$vcov.cl
                df.cl2 <- stderror2$df.cl
                dof2 <- stderror2$dof
                stderror2 <- stderror2$stderror

                cl_inter <- as.numeric(as.factor(paste(cl[,1], "-:-", cl[,2], sep = "")))

                #if cl_inter is unique; then stderror3 is robust standard error
                cl_inter.count <- table(cl_inter)
                if(max(cl_inter.count)==1){
                    meat3 <- dz * matrix(rep(c(u.hat), dim(dz)[2]), dim(dz)[1], dim(dz)[2])
                    meat3 <- as.matrix(t(meat3) %*% meat3)
                    vcov3 <- inv.xPzx%*%(t(inv.z.zx)%*%meat3%*%inv.z.zx)%*%inv.xPzx
                    vcov3 <- dim(dx)[1]/model.iv$df.original*vcov3
                    stderror3 <- c()
                    for (i in 1:dim(x)[2]) {
                        stderror3 <- c(stderror3, sqrt(vcov3[i, i]))
                    }
                    stderror3 <- as.matrix(stderror3)
                    num.cl3 <- length(cl_inter.count)
                    df.cl3 <- model.iv$df.original
                    dof3 <- model.iv$dof
                }else{
                    stderror3 <- iv.cluster.se(cl = as.matrix(cl_inter), x = x, u.hat = u.hat, dz=dz,
                                            sfe.index = sfe.index,
                                            cfe.index = cfe.index,
                                            ind = ind, df = df, df.cl = df.cl.use[3],
                                            model = model,
                                            inv.z.zx = inv.z.zx,
                                            inv.xPzx = inv.xPzx)
                    num.cl3 <- stderror3$num.cl
                    vcov3 <- stderror3$vcov.cl
                    df.cl3 <- stderror3$df.cl
                    dof3 <- stderror3$dof
                    stderror3 <- stderror3$stderror
                }

                df.cl <- c(df.cl1,df.cl2,df.cl3)
                num.cl <- min(num.cl1,num.cl2,num.cl3)
                dof.output <- list()
                dof.names <- names(dof1)
                for(sub.dof.name in dof.names){
                    min.index <- which.min(c(dof1[[sub.dof.name]][1]-dof1[[sub.dof.name]][2],
                                           dof2[[sub.dof.name]][1]-dof2[[sub.dof.name]][2],
                                           dof3[[sub.dof.name]][1]-dof3[[sub.dof.name]][2]))
                    if(min.index==1){
                        dof.output[[sub.dof.name]] <- dof1[[sub.dof.name]]
                    }
                    if(min.index==2){
                        dof.output[[sub.dof.name]] <- dof2[[sub.dof.name]]
                    }
                    if(min.index==3){
                        dof.output[[sub.dof.name]] <- dof3[[sub.dof.name]]
                    }
                }

                model.iv$dof <- dof.output
                vcov <- vcov1+vcov2-vcov3
                stderror <- sqrt(stderror1^2 + stderror2^2 - stderror3^2)
            }

            df <- min(num.cl-1,df)
            Tx <- c(model.iv$coefficients)/c(stderror)
            P_t <- NULL
            for (i in 1:length(Tx)) {
                subt <- pt(Tx[i], df)
                P_t <- c(P_t, 2 * min(1 - subt, subt))
            }

            CI <- cbind(c(model.iv$coefficients) - qt(0.975,df)*c(stderror), c(model.iv$coefficients) + qt(0.975,df)*c(stderror))
            est.coefficients <- cbind(model.iv$coefficients, stderror, Tx, P_t, CI)
            colnames(est.coefficients) <- c("Coef", "Std. Error", "t value", "Pr(>|t|)", "CI_lower", "CI_upper")
            rownames(est.coefficients) <- colnames(x)
            model.iv$est.coefficients <- est.coefficients

            #Wald Test

            fF <- try(t(model.iv$coefficients) %*% solve(vcov) %*% model.iv$coefficients,silent = T)
            if ('try-error' %in% class(fF)) {
                fF <- NULL
                F_statistic <- NULL
                warning("Number of clusters insufficient to calculate robust covariance matrix.\n")
            }
            else{
                fF <- c(fF) / dim(x)[2]
                F_statistic <- cbind(fF, dim(x)[2], df, 1 - pf(fF, dim(x)[2], df))
                colnames(F_statistic) <- c("F_statistic", "df1", "df2", "P value")
            }

            model.iv$proj_F_statistic <- F_statistic
            model.iv$df.residual <- df
            model.iv$df.cl <- df.cl

            df.cl.max <- max(df.cl)
            sigma2 <- t(u.hat)%*%u.hat/df.cl.max
            RMSE <- sqrt(sigma2)
            R2 <- 1 - sum(t(u.hat)%*%u.hat)/sum((data[, 1] - mean(data[, 1]))^2)
            Adj_R2 <- 1 - (1 - R2) * (dim(x)[1] - 1) / df.cl.max
            projR2 <- 1 - sum(t(u.hat)%*%u.hat)/sum((c(model$demeaned$y) - mean(model$demeaned$y))^2)
            projAdj_R2 <- 1 - (1 - projR2) * (dim(x)[1] - 1) / df.cl.max
        }
        colnames(vcov) <- rownames(vcov) <- colnames(x)
        model.iv$vcov <- vcov
        model.iv$RMSE <- RMSE
        model.iv$R2 <- R2
        model.iv$Adj_R2 <- Adj_R2
        model.iv$projR2 <- projR2
        model.iv$projAdj_R2 <- projAdj_R2
    }

    if(need.fe==TRUE){ #recover the fixed effects
        model.y <- SolveFixedEffects(matrix(y,ncol=1), fe$ptr, core.num)
        model.y <- name.fe.model(model.y, inds, fe)
        sfe.x.list <- list()
        cfe.x.list <- list()
        intercept.x <- c()

        if(identical(model.y$sfe.coefs,character(0))==FALSE){
            for(sub.sfe.name in names(model.y$sfe.coefs)){
                sfe.x.list[[sub.sfe.name]] <- model.y$sfe.coefs[[sub.sfe.name]]
            }
        }

        if(identical(model.y$cfe.coefs,character(0))==FALSE){
            for(sub.cfe.name in names(model.y$cfe.coefs)){
                cfe.x.list[[sub.cfe.name]] <- model.y$cfe.coefs[[sub.cfe.name]]
            }
        }

        intercept.x <- model.y$intercept

        if(dim(x)[2]!=0){
            for(i in 1:dim(x)[2]){
                model.x <- SolveFixedEffects(matrix(x[,i],ncol=1), fe$ptr, core.num)
                model.x <- name.fe.model(model.x, inds, fe)

                if(identical(model.y$sfe.coefs,character(0))==FALSE){
                    for(sub.sfe.name in names(model.y$sfe.coefs)){
                        sfe.x.list[[sub.sfe.name]] <- sfe.x.list[[sub.sfe.name]]-iv.coef[i,]*model.x$sfe.coefs[[sub.sfe.name]]
                    }
                }

                if(identical(model.y$cfe.coefs,character(0))==FALSE){
                    for(sub.cfe.name in names(model.y$cfe.coefs)){
                        cfe.x.list[[sub.cfe.name]] <- cfe.x.list[[sub.cfe.name]]-iv.coef[i,]*model.x$cfe.coefs[[sub.cfe.name]]
                    }
                }
                intercept.x <- intercept.x-iv.coef[i,]*model.x$intercept
            }
        }

        if(identical(cfe.x.list,list())){
            cfe.x.list <- character(0)
        }
        model.iv$sfe.coefs <- sfe.x.list
        model.iv$cfe.coefs <- cfe.x.list
        model.iv$intercept <- intercept.x
    }

    model.iv$y <- y
    model.iv$x <- x
    model.iv$z <- z
    model.iv$residuals <- u.hat
    model.iv$fitted.values <- y - u.hat
    model.iv$ols.model <- model
    model.iv$reduce.model <- model.reduce
    model.iv$demeaned <- list(dx=dx,dy=dy,dz=dz)
    model.iv$inds <- inds
    model.iv$matrix <- list(inv.x=inv.x,inv.z=inv.z,inv.z.zx=inv.z.zx,inv.xPzx=inv.xPzx,XZ=XZ,ZY=ZY)

    #all endogenous variables, extracted from x
    en.var.x <- c()
    ex.var.x <- c()
    #from z
    include.iv <- c()
    exclude.iv <- c()
    for(sub.dx in colnames(x)){
        get.ex <- matrix(sapply(as.data.frame(dz), identical, dx[,sub.dx]),nrow = 1)
        colnames(get.ex) <- colnames(z)
        if(any(get.ex)==TRUE){
            include.iv <- c(include.iv,colnames(get.ex)[which(get.ex==TRUE)])
            ex.var.x <- c(ex.var.x,sub.dx)
        }
    }
    include.iv <- unique(include.iv)
    ex.var.x <- unique(ex.var.x)
    exclude.iv <- colnames(dz)[which(!colnames(dz)%in%include.iv)]
    en.var.x <- colnames(dx)[which(!colnames(dx)%in%ex.var.x)]
    model.iv$names <- list(en.var.x=en.var.x,ex.var.x=ex.var.x,include.iv=include.iv,exclude.iv=exclude.iv)

    if(iv.test == TRUE){
        iv.test.results <- iv.test(model.iv, robust=robust, cl=cl, first = first, orthog=orthog, endog=endog)
        model.iv$tests <- iv.test.results
    }

    class(model.iv) <- "ivfastplm"
    return(model.iv)

}


#' Plot MCMC
#'
#' Makes a number of diagnostic plots to evaluate convergence in the Monte Carlo Markov Chain results.
#' @param wd directory where ASAP run is located
#' @param asap.name Base name of original dat file (without the .dat extension)
#' @param asap name of the variable that read in the asap.rdat file
#' @param mcmc.burn number of realizations to remove from start of MCMC (defaults to 0)
#' @param mcmc.thin thinning parameter for MCMC (defaults to 1)
#' @param save.plots save individual plots
#' @param od output directory for plots and csv files
#' @param plotf type of plot to save
#' @export

PlotMCMC  <- function(wd,asap.name,asap,mcmc.burn=0,mcmc.thin=1,save.plots,od,plotf){

  # kk5 <- library(plotMCMC, logical.return=T)
  # if (kk5==F) install.packages("plotMCMC" )
  # library(plotMCMC)

  f.chain <- paste0(asap.name, ".MCM" )
  #f.chain <- "asap3MCMC.dat"
  # don't run this function if chains are not present
  # just in case Enable MCMC Calculations box checked in General Tab of GUI but MCMC not actually run
  if (file.exists(paste0(wd,"\\",f.chain)) == FALSE){
    return()
  }
  chain1c <- read.table(paste0(wd,"\\",f.chain), header=T)
  ## new stuff
  niter <-  dim(chain1c)[1]
  if (niter == 0) return() # in case asap$options$do.mcmc>0 but MCMC not actually run
  chain1b <-  chain1c[(mcmc.burn+1):niter,]
  niter <-  dim(chain1b)[1]
  chain1a <-  chain1b[seq(1,niter,by=mcmc.thin),]

  bsn1c <- read.table(paste0(wd,"\\",asap.name, ".BSN"), header=T)
  niter <-  dim(bsn1c)[1]
  bsn1b <-  bsn1c[(mcmc.burn):niter,]
  niter <-  dim(bsn1b)[1]
  bsn1a <-  bsn1b[seq(1,niter,by=mcmc.thin),]
  write.table(bsn1a, file=paste0(od, "New_BSN_file.BSN"), row.names=T)
  write.table(bsn1a, file=paste0(wd, "\\New_", asap.name,".BSN"), row.names=F, col.names=F)

  niter <-  dim(chain1a)[1]
  nyears <- asap$parms$nyears
  years <- seq(asap$parms$styr, asap$parms$endyr)

  f.chain <- chain1a[,seq(1,nyears)]
  ssb.cols1 <- which(substr(names(chain1a),1,3)=="SSB")
  ssb.chain <- chain1a[,ssb.cols1[1:(length(ssb.cols1)-2)] ]
  fmult.chain <- chain1a[,which(substr(names(chain1a),1,3)=="Fmu")]
  totB.chain <- chain1a[,which(substr(names(chain1a),1,3)=="tot")]
  MSY.chain <- chain1a[,which(substr(names(chain1a),1,3)=="MSY")]
  MSY.col <- which(substr(names(chain1a),1,3)=="MSY")
  SSBmsy.chain <- chain1a[,(MSY.col+1)]
  Fmsy.chain <- chain1a[,(MSY.col+2) ]
  SSBmsy.ratio.chain <- chain1a[,(MSY.col+3) ]
  Fmsy.ratio.chain <- chain1a[,(MSY.col+4 ) ]

  # examine Trace in first and last year

  par(mfcol=c(2,1),mar=c(4,4,2,2), oma=c(1,1,1,1))
  plot(seq(1,niter), ssb.chain[,1], type='l', xlab="Iteration", ylab=paste0("SSB",years[1]) )
  plot(seq(1,niter), ssb.chain[,nyears], type='l', xlab="Iteration", ylab=paste0("SSB",years[nyears]))
  if (save.plots==T)  savePlot(paste0(od,'Trace.SSB.first.last.yr.',plotf),type=plotf)

  par(mfcol=c(2,1),mar=c(4,4,2,2), oma=c(1,1,1,1))
  plot(seq(1,niter), f.chain[,1], type='l', xlab="Iteration", ylab=paste0("Freport",years[1]) )
  plot(seq(1,niter), f.chain[,nyears], type='l', xlab="Iteration", ylab=paste0("Freport",years[nyears]))
  if (save.plots==T)  savePlot(paste0(od,'Trace.Freport.first.last.yr.',plotf),type=plotf)

  ##NEW
  # examine cumuplot in first and last year to determine if chain long enough (quartiles stabilized)
  mcmc.outs <- cbind( f.chain[,c(1,nyears)],  ssb.chain[,c(1,nyears)])
  plotMCMC::plotCumu(mcmc.outs,probs=c(0.05,0.95), div=1, xlab="Iterations",
           ylab="Median with 90% PI", lty.median=1, lwd.median=2, col.median="black", lty.outer=2, lwd.outer=1,
           col.outer="black"  )

  if (save.plots==T)  savePlot(paste0(od,'Cumu.F_and_SSB.first.last.yr.',plotf),type=plotf)

  # look at auto-correlation plot
  par(mfcol=c(2,1),mar=c(4,4,2,2))
  ac.ssb1<-acf(ssb.chain[,1], lag.max=10, plot=F)
  ac.ssb2<-acf(ssb.chain[,nyears], lag.max=10, plot=F)
  ylims <- c(1.1*min(ac.ssb1$acf,-2/sqrt(niter)), 1 )
  plot(seq(0,10), ac.ssb1$acf, xlab=paste0("Lag SSB",years[1]), ylab="ACF", type="h",ylim=ylims )
  abline(h=0, lwd=2, col='black')
  abline(h=2/sqrt(niter), col='red', lty=2)
  abline(h=-2/sqrt(niter), col='red', lty=2)

  plot(seq(0,10), ac.ssb2$acf, xlab=paste0("Lag SSB",years[nyears]), ylab="ACF", type="h",ylim=ylims )
  abline(h=0, lwd=2, col='black')
  abline(h=2/sqrt(niter), col='red', lty=2)
  abline(h=-2/sqrt(niter), col='red', lty=2)

  if (save.plots==T)  savePlot(file=paste0(od, "lag.autocorrelation.SSB.",plotf), type=plotf)

  par(mfcol=c(2,1),mar=c(4,4,2,2))
  ac.f1<-acf(f.chain[,1], lag.max=10, plot=F)
  ac.f2<-acf(f.chain[,nyears], lag.max=10, plot=F)
  ylims <- c(1.1*min(ac.f1$acf,-2/sqrt(niter)), 1 )
  plot(seq(0,10), ac.f1$acf, xlab=paste0("Lag F",years[1]), ylab="ACF", type="h",ylim=ylims )
  abline(h=0, lwd=2, col='black')
  abline(h=2/sqrt(niter), col='red', lty=2)
  abline(h=-2/sqrt(niter), col='red', lty=2)

  plot(seq(0,10), ac.f2$acf, xlab=paste0("Lag F",years[nyears]), ylab="ACF", type="h",ylim=ylims )
  abline(h=0, lwd=2, col='black')
  abline(h=2/sqrt(niter), col='red', lty=2)
  abline(h=-2/sqrt(niter), col='red', lty=2)

  if (save.plots==T)  savePlot(file=paste0(od, "lag.autocorrelation.Freport.",plotf), type=plotf)

  # examine Distribution in first and last year
  ssb1.hist<-hist(ssb.chain[,1],breaks = "Sturges", include.lowest = TRUE, right = TRUE, plot=F)
  ssb2.hist<-hist(ssb.chain[,nyears],breaks = "Sturges", include.lowest = TRUE, right = TRUE, plot=F)
  xlims <- c(min(ssb1.hist$mids, ssb2.hist$mids), max(ssb1.hist$mids, ssb2.hist$mids))

  x1 <- (ssb1.hist$mids)
  y1 <- (ssb1.hist$counts)
  x2 <- (ssb2.hist$mids)
  y2 <- (ssb2.hist$counts)

  par(mfrow=c(2,1) )
  plot(x1,y1, type="l",lty=2,col="blue",lwd=4,xlab=paste0("SSB", years[1]), ylab="Freq",
       ylim=c(0, max( 1.02*y1)), xlim=c(0.98*xlims[1], 1.02*xlims[2]) )
  abline(v=asap$SSB[1], col='red', lty=4)
  legend('topleft', legend=c("MCMC", "Point Est."), col=c("blue", "red"), lwd=c(2,2),
         lty=c(1,4), cex=0.85 )

  plot(x2,y2, type="l",lty=2,col="blue",lwd=4,xlab=paste0("SSB", years[nyears]), ylab="Freq",
       ylim=c(0, max( 1.02*y2)), xlim=c(0.98*xlims[1], 1.02*xlims[2]) )
  abline(v=asap$SSB[nyears], col='red', lty=4)
  if (save.plots==T)  savePlot(paste0(od, 'Distribution.SSB.first.last.yr.',plotf), type=plotf)

  f1.hist<-hist(f.chain[,1],breaks = "Sturges", include.lowest = TRUE, right = TRUE, plot=F)
  f2.hist<-hist(f.chain[,nyears],breaks = "Sturges", include.lowest = TRUE, right = TRUE, plot=F)
  xlims <- c(min(f1.hist$mids, f2.hist$mids), max(f1.hist$mids, f2.hist$mids))

  x1 <- (f1.hist$mids)
  y1 <- (f1.hist$counts)
  x2 <- (f2.hist$mids)
  y2 <- (f2.hist$counts)

  par(mfrow=c(2,1) )
  plot(x1,y1, type="l",lty=2,col="blue",lwd=4,xlab=paste0("Freport", years[1]), ylab="Freq",
       ylim=c(0, max( 1.02*y1)), xlim=c(0.98*xlims[1], 1.02*xlims[2]) )
  abline(v=asap$F.report[1], col='red', lty=4)
  legend('topleft', legend=c("MCMC", "Point Est."), col=c("blue", "red"), lwd=c(2,2),
         lty=c(1,4), cex=0.85 )

  plot(x2,y2, type="l",lty=2,col="blue",lwd=4,xlab=paste0("Freport", years[nyears]), ylab="Freq",
       ylim=c(0, max( 1.02*y2)), xlim=c(0.98*xlims[1], 1.02*xlims[2]) )
  abline(v=asap$F.report[nyears], col='red', lty=4)

  if (save.plots==T)  savePlot(paste0(od, 'Distribution.Freport.first.last.yr.',plotf), type=plotf)

  fm1.hist<-hist(fmult.chain[,1],breaks = "Sturges", include.lowest = TRUE, right = TRUE, plot=F)
  fm2.hist<-hist(fmult.chain[,nyears],breaks = "Sturges", include.lowest = TRUE, right = TRUE, plot=F)
  xlims <- c(min(fm1.hist$mids, fm2.hist$mids), max(fm1.hist$mids, fm2.hist$mids))

  x1 <- (fm1.hist$mids)
  y1 <- (fm1.hist$counts)
  x2 <- (fm2.hist$mids)
  y2 <- (fm2.hist$counts)
  full.f <- apply(asap$F.age,1,max)

  par(mfrow=c(2,1) )
  plot(x1,y1, type="l",lty=2,col="blue",lwd=4,xlab=paste0("Full F", years[1]), ylab="Freq",
       ylim=c(0, max( 1.02*y1)), xlim=c(0.98*xlims[1], 1.02*xlims[2]) )
  abline(v=full.f[1], col='red', lty=4)
  legend('topleft', legend=c("MCMC", "Point Est."), col=c("blue", "red"), lwd=c(2,2),
         lty=c(1,4), cex=0.85 )

  plot(x2,y2, type="l",lty=2,col="blue",lwd=4,xlab=paste0("Full F", years[nyears]), ylab="Freq",
       ylim=c(0, max( 1.02*y2)), xlim=c(0.98*xlims[1], 1.02*xlims[2]) )
  abline(v=full.f[nyears], col='red', lty=4)

  if (save.plots==T)  savePlot(paste0(od, 'Distribution.Fmult.first.last.yr.',plotf), type=plotf)

  b1.hist<-hist(totB.chain[,1],breaks = "Sturges", include.lowest = TRUE, right = TRUE, plot=F)
  b2.hist<-hist(totB.chain[,nyears],breaks = "Sturges", include.lowest = TRUE, right = TRUE, plot=F)
  xlims <- c(min(b1.hist$mids, b2.hist$mids), max(b1.hist$mids, b2.hist$mids))

  x1 <- (b1.hist$mids)
  y1 <- (b1.hist$counts)
  x2 <- (b2.hist$mids)
  y2 <- (b2.hist$counts)
  tot.B <- asap$tot.jan1.B

  par(mfrow=c(2,1) )
  plot(x1,y1, type="l",lty=2,col="blue",lwd=4,xlab=paste0("Jan-1 B", years[1]), ylab="Freq",
       ylim=c(0, max( 1.02*y1)), xlim=c(0.98*xlims[1], 1.02*xlims[2]) )
  abline(v=tot.B[1], col='red', lty=4)
  legend('topleft', legend=c("MCMC", "Point Est."), col=c("blue", "red"), lwd=c(2,2),
         lty=c(1,4), cex=0.85 )

  plot(x2,y2, type="l",lty=2,col="blue",lwd=4,xlab=paste0("Jan-1 B", years[nyears]), ylab="Freq",
       ylim=c(0, max( 1.02*y2)), xlim=c(0.98*xlims[1], 1.02*xlims[2]) )
  abline(v=tot.B[nyears], col='red', lty=4)

  if (save.plots==T)  savePlot(paste0(od, 'Distribution.Jan1.B.first.last.yr.',plotf), type=plotf)

  ####   Probability Interval Plots
  #plot 95% PI

  #sort
  par(mfrow=c(1,1), mar=c(4,4,2,3), oma=c(1,1,1,1)  )

  ssb.sort<- (apply(ssb.chain,2,sort ))
  p5 <- trunc( dim(ssb.sort)[1] *.05)
  p95 <-  trunc( dim(ssb.sort)[1] *.95)

  p50 <- median(dim(ssb.sort)[1])
  p10 <-  trunc( dim(ssb.sort)[1] *.10)
  p90 <-  trunc( dim(ssb.sort)[1] *.90)

  plot(years, ssb.sort[p5,], type='l', col='grey35', lwd=2, xlab='Year',
       ylab='', ylim=c(0,1.03*max(ssb.sort[p95,])), axes=F  )
  axis(side=1, at=years[seq(1,nyears,by=2)], labels=years[seq(1,nyears,by=2)], las=2)
  axis(side=2, at=pretty(seq(0,1.01*max(ssb.sort)), n=10) ,
       labels=format(pretty(seq(0,1.01*max(ssb.sort)), n=10), scientific=T), las=1)
  axis(side=4, at=pretty(seq(0,1.01*max(ssb.sort)), n=10) ,
       labels=format(pretty(seq(0,1.01*max(ssb.sort)), n=10), scientific=T), las=1)
  box()
  mtext(side=2, text="SSB", outer=T)
  lines( years, ssb.sort[p95,] , col='grey35', lwd=2)
  lines( years, apply(ssb.sort,2,median) , col='red', lwd=2)
  lines( years, asap$SSB , col='green3', lwd=1)
  points( years, asap$SSB , col='green3', pch=17, cex=0.7)

  legend('topleft', horiz=T, legend=c("5th, 95th", "Median","Point Est."),
         col=c("grey35", "red", "green3"), lwd=c(2,2,2), lty=c(1,1,1), cex=0.85,
         pch=c(1,1,17), pt.cex=c(0,0,1) )

  if (save.plots==T)  savePlot(paste0(od, "SSB.90PI.", plotf), type=plotf)

  ssb.pi <- cbind(years, "5th"=ssb.sort[p5,], "Median"=apply(ssb.sort,2,median), "95th"=ssb.sort[p95,])
  write.csv(ssb.pi, file=paste0(od, "ssb.90pi_",asap.name,".csv"),
            row.names=F )

  f.sort <- (apply(f.chain,2,sort ))
  p5 <- trunc( dim(f.sort)[1] *.05)
  p95 <- trunc( dim(f.sort)[1] *.95)

  p50 <- median(dim(f.sort)[1])
  p10 <- trunc( dim(f.sort)[1] *.10)
  p90 <- trunc( dim(f.sort)[1] *.90)

  par(mfrow=c(1,1), mar=c(4,4,2,3), oma=c(1,1,1,1)  )
  plot(years, f.sort[p5,], type='l', col='grey35', lwd=2, xlab='Year',
       ylab='Freport', ylim=c(0,1.1*max(f.sort[p95,])), axes=F  )
  axis(side=1, at=years[seq(1,nyears,by=2)], labels=years[seq(1,nyears,by=2)], las=2)
  axis(side=2, at=pretty(seq(0,1.01*max(f.sort), by=0.1), n=10) ,
       labels=pretty(seq(0,1.01*max(f.sort), by=0.1), n=10), las=1)
  axis(side=4, at=pretty(seq(0,1.01*max(f.sort), by=0.1), n=10) ,
       labels=pretty(seq(0,1.01*max(f.sort), by=0.1), n=10), las=1)
  box()

  lines( years, f.sort[p95,] , col='grey35', lwd=2)
  lines( years, apply(f.sort,2,median) , col='red', lwd=2)
  lines( years, asap$F.report , col='green3', lwd=1)
  points( years, asap$F.report , col='green3', pch=17, cex=0.7)
  legend('topleft', horiz=T, legend=c("5th, 95th", "Median","Point Est."),
         col=c("grey35", "red", "green3"), lwd=c(2,2,2), lty=c(1,1,1), cex=0.85,
         pch=c(1,1,17), pt.cex=c(0,0,1) )

  if (save.plots==T)  savePlot(paste0(od, "Freport.90PI.", plotf), type=plotf)

  Freport.pi <- cbind(years, "5th"=f.sort[p5,], "Median"=apply(f.sort,2,median), "95th"=f.sort[p95,])
  write.csv(Freport.pi, file=paste0(od, "Freport.90pi_",asap.name,".csv"),   row.names=F)

  fm.sort <- (apply(fmult.chain,2,sort ))
  p5 <- trunc( dim(fm.sort)[1] *.05)
  p95 <- trunc( dim(fm.sort)[1] *.95)

  p50 <- median(dim(fm.sort)[1])
  p10 <- trunc( dim(fm.sort)[1] *.10)
  p90 <- trunc( dim(fm.sort)[1] *.90)

  par(mfrow=c(1,1), mar=c(4,4,2,3), oma=c(1,1,1,1)  )
  plot(years, fm.sort[p5,], type='l', col='grey35', lwd=2, xlab='Year',
       ylab='Full F', ylim=c(0,1.1*max(fm.sort[p95,])), axes=F  )
  axis(side=1, at=years[seq(1,nyears,by=2)], labels=years[seq(1,nyears,by=2)], las=2)
  axis(side=2, at=pretty(seq(0,1.01*max(fm.sort), by=0.1), n=10) ,
       labels=pretty(seq(0,1.01*max(fm.sort), by=0.1), n=10), las=1)
  axis(side=4, at=pretty(seq(0,1.01*max(fm.sort), by=0.1), n=10) ,
       labels=pretty(seq(0,1.01*max(fm.sort), by=0.1), n=10), las=1)
  box()

  lines( years, fm.sort[p95,] , col='grey35', lwd=2)
  lines( years, apply(fm.sort,2,median) , col='red', lwd=2)
  lines( years, full.f , col='green3', lwd=1)
  points( years, full.f, col='green3', pch=17, cex=0.7)
  legend('topleft', horiz=T, legend=c("5th, 95th", "Median","Point Est."),
         col=c("grey35", "red", "green3"), lwd=c(2,2,2), lty=c(1,1,1), cex=0.85,
         pch=c(1,1,17), pt.cex=c(0,0,1) )

  if (save.plots==T)  savePlot(paste0(od, "Full.F.90PI.", plotf), type=plotf)

  Full.F.pi <- cbind(years, "5th"=fm.sort[p5,], "Median"=apply(fm.sort,2,median), "95th"=fm.sort[p95,])
  write.csv(Full.F.pi, file=paste0(od, "Full.F.90pi_",asap.name,".csv"), row.names=F)

  tb.sort <- (apply(totB.chain,2,sort ))
  p5 <- trunc( dim(tb.sort)[1] *.05)
  p95 <- trunc( dim(tb.sort)[1] *.95)

  p50 <- median(dim(tb.sort)[1])
  p10 <- trunc( dim(tb.sort)[1] *.10)
  p90 <- trunc( dim(tb.sort)[1] *.90)

  par(mfrow=c(1,1), mar=c(4,4,2,3), oma=c(1,1,1,1)  )
  plot(years, tb.sort[p5,], type='l', col='grey35', lwd=2, xlab='Year',
       ylab='', ylim=c(0,1.03*max(tb.sort[p95,])), axes=F  )
  axis(side=1, at=years[seq(1,nyears,by=2)], labels=years[seq(1,nyears,by=2)], las=2)
  axis(side=2, at=pretty(seq(0,1.01*max(tb.sort), by=max(tb.sort)/10), n=10) ,
       labels=format(pretty(seq(0,1.01*max(tb.sort), by=max(tb.sort)/10), n=10), scientific=T), las=1)
  axis(side=4, at=pretty(seq(0,1.01*max(tb.sort), by=max(tb.sort)/10), n=10) ,
       labels=format(pretty(seq(0,1.01*max(tb.sort), by=max(tb.sort)/10), n=10), scientific=T), las=1)

  box()
  mtext(side=2, text="Jan-1 Biomass", outer=T)
  lines( years, tb.sort[p95,] , col='grey35', lwd=2)
  lines( years, apply(tb.sort,2,median) , col='red', lwd=2)
  lines( years, asap$tot.jan1.B , col='green3', lwd=1)
  points( years, asap$tot.jan1.B, col='green3', pch=17, cex=0.7)
  legend('topleft', horiz=T, legend=c("5th, 95th", "Median","Point Est."),
         col=c("grey35", "red", "green3"), lwd=c(2,2,2), lty=c(1,1,1), cex=0.85,
         pch=c(1,1,17), pt.cex=c(0,0,1) )

  if (save.plots==T)  savePlot(paste0(od, "Jan1.B.90PI.", plotf), type=plotf)

  Tot.B.pi <- cbind(years, "5th"=tb.sort[p5,], "Median"=apply(tb.sort,2,median), "95th"=tb.sort[p95,])
  write.csv(Tot.B.pi, file=paste0(od, "Jan1.B.90pi_",asap.name,".csv"), row.names=F)

  return()
}  # end function


#' @title Livestock resilience model
#'
#' @description A model of resilience in arid rangelands.
#' @usage
#' library(livestock)
#'
#'
#' library(caspr)
#' ca(l, livestock, parms = p)
#'
#' @param b environmental quality
#' @param m intrinsic plant mortality, i.e. inverse of av. lifespan
#' @param r max. regeneration rate of plants
#' @param K carrying capacity of the landscape (i.e. global competition)
#' @param f local facilitation
#' @param c local competition
#' @param L livestock density
#' @param a attack rate of livestock
#' @param h handling time of livestock
#' @param q hill-exponent of livestock
#' @param p associational resistance against livestock grazing
#' @param v attractant-decoy effect of plants to livestock
#'
#' @author F.D. Schneider
#' @family models
#' @details
#' An unpublished, generalized model of positive and negative local feedbacks in arid rangelands, including mechanisms such as local facilitation, competition, associational resistance and attractant-decoy.
#'
#' @export

"livestock"

livestock <- list(
  name = "Livestock resilience model",
  ref = NA , # a bibliographic reference,
  states = c("1", "0"),
  cols = c("black", "white"),
  template = ini_rho(rho_1 = 0.9999),
  parms = list(
    r = 1,
    b = 1,
    K = 1,
    alpha = 0,
    c = 0,
    f = 0,
    m = 0.05,
    a = 10,
    h = 20,
    L = 1,
    q = 0,
    v = 0,
    p = 0
  ),
  pair = function(t, rho, parms = model_parms) {

    # insert equations here
    delta_1 = (1-rho[[1]]) * colonization(rho, parms) - rho[[1]] * death(rho, parms)
    delta_11 = 2 * (rho[[1]]-rho[[2]]) * colonization(rho, parms) - 2 * rho[[2]] * death(rho, parms)

    if(rho[[1]] < 1e-6) {
      out <- list(c(
        rho_1 = 0,
        rho_11 = 0
      )  )
    } else {
      out <- list(c(
        rho_1 = delta_1,
        rho_11 = delta_11
      )  )
    }
    return(out)
  },
  pairmeanfield = function(t, rho, parms = model_parms) {
    pair(t, ini_rho(rho[[1]]), parms)
  },
  meanfield = function(t, rho, parms = model_parms) {

    rho <- ini_rho(rho[[1]])
    delta_1 <- (1-rho[[1]])*colonization(rho, parms) - rho[[1]]*death(rho, parms)

    if(rho[[1]]+delta_1 < 1e-6) {
      out <- list(c(
        rho_1 = 0,
        rho_11 = 0
      )  )
    } else {
      out <- list(c(
        rho_1 = delta_1,
        rho_11 = delta_1
      )  )
    }
    return(out)
  },
  update = function(x_old, parms, subs = 24, i = i) {  #for cellular automata simulation in package caspr

    x_new <- x_old

    for(s in 1:subs) {

      # define update procedures depending on parms

      # model specific part:
      # 1 - setting time-step parameters
      rho_one <- as.numeric(sum(x_old$cells == "1")/(x_old$dim[1]*x_old$dim[2])) # get initial vegetation cover
      q_one_one <- neighbors(x_old, "1")/4  # count local density of occupied fields for each cell

      # 2 - drawing random numbers
      rnum <- runif(x_old$dim[1]*x_old$dim[2]) # one random number between 0 and 1 for each cell

      # 3 - setting transition probabilities
      growth <- colonization(ini_rho(rho_one, q_11 = q_one_one), parms) *1/subs  # recolonisation rates of all cells

      growth[growth < 0] <- 0

      death <- death(ini_rho(rho_one, q_11 = q_one_one), parms) *1/subs   # set probability of death for each cell

      death[death < 0] <- 0

      # check for sum of probabilities to be inferior 1 and superior 0
      if(any(c(growth, death) > 1 )) warning(paste("a set probability is exceeding 1 ! decrease delta!!!"))
      #if(any(c(growth, death) < 0)) warning(paste("a set probability falls below 0 in time step", i, "! balance parameters!!!"))

      # 4 - apply transition probabilities

      x_new$cells[which(x_old$cells == "0" & rnum <= growth)] <- "1"
      x_new$cells[which(x_old$cells == "1" & rnum <= death)] <- "0"

      # 5- store x_new as next x_old

      x_old <- x_new

    }

    return(x_new)

  }

)

class(livestock) <- c("ca_model", "list")