R/findProcessingLevel.R

Defines functions findProcessingLevel

Documented in findProcessingLevel

##' Find Processing Level
##' 
##' The function finds the processing level of the item in relation to the rest
##' of the commodity items.  The processing level is zero for all nodes which
##' have no inputs (i.e. they can be processed in the first round). A node with
##' inputs has it's processing level defined as 1 greater than the max
##' processing level of all of it's input nodes.  Thus, nodes at level 0 are
##' processed first, as their processing doesn't depend on any other commodites.
##' Then, nodes at processing level 1 are processed because all their inputs
##' (level 0 nodes) have been computed.  All nodes at a fixed processing level
##' can thus be computed in one step.
##' 
##' @param edgeData The edge data, typically from the function buildEdges
##' @param from The column name of edgeData corresponding to the from node.
##' @param to The column name of edgeData corresponding to the target node.
##' @param plot Logical, indicates of the graph should be plotted.
##' @param aupusParam A list of running parameters to be used in pulling the
##'   data. Typically, this is generated from getAupusParameter (see that
##'   function for a description of the required elements).
##' @param errorOnLoop Logical.  Should the function throw an error if a loop is
##'   detected in the edgeData?  If such a loop is detected, a plot is generated
##'   to aid the user in finding this loop.
##'   
##' @return A data.table providing the processing level for each of the items.
##'   
##' @import igraph
##'   
##' @export
##' 

findProcessingLevel = function(edgeData, from, to, plot = FALSE,
                               aupusParam = list(itemVar = "temp"),
                               errorOnLoop = TRUE){
    e = edgeData[, c(from, to), with = FALSE]
    v = unique(unlist(edgeData[, c(from, to), with = FALSE]))
    processingGraph = igraph::graph.data.frame(d = e, vertices = v, directed = TRUE)
    if(plot == TRUE)
        plot(processingGraph, vertex.size = 6, edge.arrow.size = 0.5)    
    root = names(which(igraph::degree(processingGraph, mode = "in") == 0 &
                           igraph::degree(processingGraph, mode = "out") > 0))

    processingLevel =
        igraph::shortest.paths(processingGraph, v = igraph::V(processingGraph),
                               to = igraph::V(processingGraph)[c(root)], mode = "in")

    ## Take the finite maximum level from processing level
    finalLevels = apply(processingLevel, 1,
        FUN = function(x) max(x[is.finite(x)], na.rm = TRUE))

    finalLevels.dt = data.table(names(finalLevels), finalLevels)
    setnames(finalLevels.dt, c(aupusParam$itemVar, "processingLevel"))
    
    if(errorOnLoop && finalLevels.dt[, min(processingLevel) == -Inf]){
        loopNodes = finalLevels.dt[processingLevel == -Inf,
                                   get(aupusParam$itemVar)]
        graph = graph.data.frame(edges[get(from) %in% loopNodes |
                                         get(to) %in% loopNodes, ])
        plot(graph)
        stop("Loops detected in commodity tree!  Check vertices:\n",
             paste(loopNodes, collapse = "\n"))
    }
    return(finalLevels.dt[order(processingLevel), ])
}
SWS-Methodology/faoswsStandardization documentation built on Feb. 7, 2022, 5:05 a.m.