#' Logging simulation
#'
#'@description This function allows to simulate a timber and fuel wood logging
#' on a forest plot. It covers: harvestable zones definition, tree selection,
#' secondary skidding trails layout, tree felling, timber harvested, fuel wood
#' volume and short-term damages quantification. This simulator is
#' individual-centred, spatialised, and takes into account the topography and
#' the hydrographic network.
#'
#'@param inventory Input forest inventory for 1 plot and 1 census year (see the
#' inputs formats and metadata in the vignette or in
#' \code{\link{Paracou6_2016}}) (data.frame)
#' The columns required are:
#' - *Forest* (to apply the corresponding volume formula)
#' - *idTree*
#' - *Xutm* and *Yutm*
#' - *CodeAlive*
#' - *Family*, *Genus*, and *Species*
#' - *CircCorr*
#' The optional columns are
#' - *Plot* (1 value)
#' - *CensusYear* (1 value)
#'
#'@param plotmask Inventoried plot mask
#'(SpatialPolygonsDataFrame **with a crs in UTM**)
#'
#'@param topography Digital terrain model (DTM) of the inventoried plot (LiDAR,
#' 1m resolution)
#' (RasterLayer **with a crs in UTM**) (See \code{\link{DTMParacou}})
#' We advise you to generate your raster with Qgis rather than with the
#' 'raster' package on R.
#'
#'@param creekverticaldistance Relative vertical distance
#' (1 m resolution) from nearest channel network
#' (RasterLayer **with a crs in UTM**) (See \code{\link{CreekDistances}})
#' To generate creek distances: \code{\link{CreekDistances}} in 'Articles'.
#'
#'@param creekhorizontaldistance Relative horizontal distance
#' (1 m resolution) from nearest channel network
#' (RasterLayer **with a crs in UTM**) (See \code{\link{CreekDistances}})
#' To generate creek distances: \code{\link{CreekDistances}} in 'Articles'.
#'
#'@param speciescriteria Table of species exploitability criteria : species
#' names, economic interest level, minimum and maximum felling diameter, in the
#' same format of \code{\link{SpeciesCriteria}} (2 levels of commercial
#' species) (data.frame)
#'
#'@param volumeparameters Volume parameters table (in the same format of
#' \code{\link{ForestZoneVolumeParametersTable}}) to compute the harvestable
#' volume of each tree, depend to its geographic zone if several locations
#' (data.frame)
#'
#'@param scenario Logging scenario among: "RIL1", "RIL2broken", "RIL2", "RIL3",
#' "RIL3fuel", "RIL3fuelhollow" or "manual"(character) (see the
#' vignette for details)
#'
#'@param objective Objective volume (m3/ha) (numeric)
#'
#'@param fuel Fuel wood exploitation: no exploitation = "0", exploitation of
#' damage and unused part of logged trees for fuel = "1", exploitation of
#' hollow trees, damage and and unused part of the log for fuel = "2"
#' If fuel wood exploitation (fuel = "1" or "2") the tree will be recovered
#' from the crown with a grapple if possible (respected grapple conditions).
#' If not, recovery at the foot with a cable at an angle to the trail.
#' Avoid future/reserve trees if chosen.
#'
#'@param diversification Possibility to log other species in addition to the
#' main commercial species (species with a value of 2 for commercial in the
#' \code{\link{SpeciesCriteria}} table) (logical)
#'
#'@param winching Tree recovery =
#' "0": no cable or grapple (trail to tree foot)
#' "1": only cable (default = 40m)
#' "2": grapple (default = 6m) + cable (grapple priority)
#' If grapple + cable (winching = "2") without fuel wood (fuel = "0")
#' recovery of the tree foot with grapple if possible (respected grapple
#' conditions) otherwise with cable with angle to the trail.
#' Avoidance of future/reserves if chosen.
#'
#'@param directionalfelling Directional felling =
#' "0": only to direct the foot of the tree towards the trail
#' "1": to direct the foot of the tree towards the trail + to avoid damage to
#' future and reserve trees if possible
#' "2": to avoid damage to future and reserve trees if possible
#' + orientation angle to the trail. Among the 2 possible angle positions,
#' the position that favours the return to the main trail should be chosen.
#' The angle to the trail is favoured to avoid future/reserve trees.
#' If the avoidance of future/reserve trees could not be performed,
#' a message is returned.
#'
#'@param specieslax Allow diversification if stand is too poor to reach the
#' objective volume without diversification, = FALSE by
#' default (logical)
#'
#'@param objectivelax Allow exploitation in case of non-achievement of the
#' objective volume (if stand too poor), = FALSE by default (logical)
#'
#'@param crowndiameterparameters Crown diameter allometry parameters table (in
#' the same format of \code{\link{ParamCrownDiameterAllometry}}) to compute the
#' crown diameter of each tree, depend to its DBH (Diameter at Breast Height)
#' and its Species, Genus or Family names (Aubry-Kientz et al.2019).
#' (data.frame)
#'
#'@param seedsim The seed set for the uniform random-number generator (numeric).
#' Default = NULL
#'
#'@param debug Option to enable writing error environment in working directory,FALSE by default (logical).
#'
#'@param advancedloggingparameters Other parameters of the logging simulator
#' \code{\link{loggingparameters}} (list)
#'
#'@param iter Number of iterations (numeric). Default = 1.
#'@param cores Number of cores for parallelization (numeric). Default = 1.
#'
#'@return A large list of 40 elements for each iteration, contained in a list.
#' Input inventory (data.frame) with logging informations (list) (see the
#' outputs metadata in the vignette or
#' \code{\link{LoggingSimulationOutputs_iter}}).
#'
#'@section Paying attention to inputs - important source of error:
#'Common error sources:
#' - no crs
#' - crs with accent
#' - *topography* and *plotmask* do not match
#' - *topography* import as R Worspace (you must import it as a .tif file)
#' - *Forest* name of the *inventory* doesn't match with the *Forest* name in
#' *volumeparameters* table
#'
#'@seealso \code{\link{Paracou6_2016}}, \code{\link{SpeciesCriteria}},
#' \code{\link{ForestZoneVolumeParametersTable}},
#' \code{\link{ParamCrownDiameterAllometry}}, \code{\link{loggingparameters}},
#'
#' \code{\link{addtreedim}}, \code{\link{treeselection}},
#' \code{\link{harvestable}}, \code{\link{selected}},
#' \code{\link{futurereserve}}, \code{\link{treefelling}},
#' \code{\link{createcanopy}}, \code{\link{treefromthesky}},
#' \code{\link{felling1tree}}, \code{\link{rotatepolygon}},
#' \code{\link{getgeometry}}, \code{\link{timberharvestedvolume}},
#' \code{\link{harvestablefuelwood}}
#'
#'@export
#'
#'@importFrom parallel makePSOCKcluster clusterExport parLapply stopCluster
#'@importFrom doSNOW registerDoSNOW
#'@importFrom foreach foreach %dopar%
#'@importFrom utils setTxtProgressBar txtProgressBar
#'@importFrom tryCatchLog tryLog
#'
#' @examples
#' \dontrun{
#' data(Paracou6_2016) # inventory
#' data(DTMParacou) # topography
#' data(CreekDistances) # relative elevation
#' data(SpeciesCriteria) # species exploitability criteria
#' data(ForestZoneVolumeParametersTable) # volume parameters
#' data(ParamCrownDiameterAllometry) # parameters values of the crown diameter allometry
#'
#' LoggingSimulationOutputs_iter <- loggingsimulation(
#' Paracou6_2016, plotmask = PlotMask, topography = DTMParacou,
#' creekverticaldistance = CreekDistances$distvert,
#' creekhorizontaldistance = CreekDistances$disthorz,
#' speciescriteria = SpeciesCriteria,
#' volumeparameters = ForestZoneVolumeParametersTable, scenario = "manual",
#' objective = 10, fuel = "2", diversification = TRUE, winching = "0",
#' directionalfelling = "2", specieslax = FALSE, objectivelax = TRUE,
#' crowndiameterparameters = ParamCrownDiameterAllometry,
#' advancedloggingparameters = loggingparameters(), iter = 2, cores = 2)
#' }
#'
loggingsimulation <- function(
inventory,
plotmask,
topography,
creekverticaldistance,
creekhorizontaldistance,
speciescriteria,
volumeparameters,
scenario,
objective = NULL,
fuel = NULL,
diversification = NULL,
winching = NULL,
directionalfelling = NULL,
specieslax = FALSE,
objectivelax = FALSE,
crowndiameterparameters = ParamCrownDiameterAllometry,
seedsim = NULL,
debug = FALSE,
advancedloggingparameters = loggingparameters(),
iter = 1,
cores = 1
){
# Check args
if(!all(unlist(lapply(list(iter, cores), inherits, "numeric"))))
stop("The 'iter' and 'cores' arguments of the 'loggingsimulation' function must be numeric")
# Global variables
j <- ParamCrownDiameterAllometry <- NULL
seedsim <-if(length(seedsim) < iter){round(runif(n = iter, min = 1, max = 2^23))}
# apply versions
# replicate(iter, loggingsimulation1(inventory = inventory,
# plotmask = plotmask,
# topography = topography,
# creekdistances = creekdistances,
# speciescriteria = speciescriteria,
# volumeparameters = volumeparameters,
# scenario = scenario,
# objective = objective,
# fuel = fuel,
# diversification = diversification,
# winching = winching,
# directionalfelling = directionalfelling,
# specieslax = specieslax,
# objectivelax = objectivelax,
# crowndiameterparameters = crowndiameterparameters,
# advancedloggingparameters = advancedloggingparameters),
# simplify = F)
#
# lapply(seq_len(iter), function(x) loggingsimulation1(inventory = inventory,
# plotmask = plotmask,
# topography = topography,
# creekdistances = creekdistances,
# speciescriteria = speciescriteria,
# volumeparameters = volumeparameters,
# scenario = scenario,
# objective = objective,
# fuel = fuel,
# diversification = diversification,
# winching = winching,
# directionalfelling = directionalfelling,
# specieslax = specieslax,
# objectivelax = objectivelax,
# crowndiameterparameters = crowndiameterparameters,
# advancedloggingparameters = advancedloggingparameters)
# )
#
# # purr versions
# purr::rerun(iter, loggingsimulation1(inventory = inventory,
# plotmask = plotmask,
# topography = topography,
# creekdistances = creekdistances,
# speciescriteria = speciescriteria,
# volumeparameters = volumeparameters,
# scenario = scenario,
# objective = objective,
# fuel = fuel,
# diversification = diversification,
# winching = winching,
# directionalfelling = directionalfelling,
# specieslax = specieslax,
# objectivelax = objectivelax,
# crowndiameterparameters = crowndiameterparameters,
# advancedloggingparameters = advancedloggingparameters)
# )
#
# purr::map(seq_len(iter), ~ loggingsimulation1(inventory = inventory,
# plotmask = plotmask,
# topography = topography,
# creekdistances = creekdistances,
# speciescriteria = speciescriteria,
# volumeparameters = volumeparameters,
# scenario = scenario,
# objective = objective,
# fuel = fuel,
# diversification = diversification,
# winching = winching,
# directionalfelling = directionalfelling,
# specieslax = specieslax,
# objectivelax = objectivelax,
# crowndiameterparameters = crowndiameterparameters,
# advancedloggingparameters = advancedloggingparameters)
# )
#
#
# Parallelization version
# For Windows
# cl <- makePSOCKcluster(getOption("cl.cores", cores)) # create a cluster
#
# # clusterEvalQ(cl, set.seed(41)) # https://stackoverflow.com/questions/58631433/how-to-set-seeds-when-using-parallel-package-in-r
#
# clusterExport(cl, varlist = c("inventory", "plotmask","topography","creekdistances",
# "speciescriteria","volumeparameters","scenario","objective",
# "fuel","diversification","winching","directionalfelling",
# "specieslax","objectivelax","crowndiameterparameters","advancedloggingparameters"),
# envir = environment()) # cluster environment
#
# # try() to catch the error and continue
# output <- parLapply(cl, seq_len(iter), function(x) try(loggingsimulation1(inventory = inventory,
# plotmask = plotmask,
# topography = topography,
# creekdistances = creekdistances,
# speciescriteria = speciescriteria,
# volumeparameters = volumeparameters,
# scenario = scenario,
# objective = objective,
# fuel = fuel,
# diversification = diversification,
# winching = winching,
# directionalfelling = directionalfelling,
# specieslax = specieslax,
# objectivelax = objectivelax,
# crowndiameterparameters = crowndiameterparameters,
# advancedloggingparameters = advancedloggingparameters)))
#
# stopCluster(cl) # stop the cluster
# For other OS
# parallel::mclapply(seq_len(iter), function(x) loggingsimulation1(inventory = inventory,
# plotmask = plotmask,
# topography = topography,
# creekdistances = creekdistances,
# speciescriteria = speciescriteria,
# volumeparameters = volumeparameters,
# scenario = scenario,
# objective = objective,
# fuel = fuel,
# diversification = diversification,
# winching = winching,
# directionalfelling = directionalfelling,
# specieslax = specieslax,
# objectivelax = objectivelax,
# crowndiameterparameters = crowndiameterparameters,
# advancedloggingparameters = advancedloggingparameters),
# mc.cores = cores)
# foreach version
i <- NULL
cl <- parallel::makeCluster(cores)
doSNOW::registerDoSNOW(cl)
if(interactive()) pb <- txtProgressBar(max = iter, style = 3)
progress <- function(n) if(interactive()) setTxtProgressBar(pb, n)
opts <- list(progress = progress)
output <- foreach::foreach(j=1:iter,.packages = c("LoggingLab","tryCatchLog"),
.options.snow = opts) %dopar% {
simtry <- tryLog(loggingsimulation1(inventory = inventory,
plotmask = plotmask,
topography = topography,
creekverticaldistance,
creekhorizontaldistance,
speciescriteria = speciescriteria,
volumeparameters = volumeparameters,
scenario = scenario,
objective = objective,
fuel = fuel,
diversification = diversification,
winching = winching,
directionalfelling = directionalfelling,
specieslax = specieslax,
objectivelax = objectivelax,
crowndiameterparameters = crowndiameterparameters,
seed = seedsim[j],
advancedloggingparameters = advancedloggingparameters), write.error.dump.file = debug)
if (inherits(simtry, "try-error")) {
return(list("error" = simtry, "seed" = seedsim[j]))
}else{return(simtry)
}
}
close(pb)
stopCluster(cl)
return(output)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.