Initial Script
This commit is contained in:
218
MESOonline.R
Normal file
218
MESOonline.R
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
library(DT)
|
||||||
|
library(shiny)
|
||||||
|
library(shinyBS)
|
||||||
|
library(shinyjs)
|
||||||
|
library(shinydashboard)
|
||||||
|
library(htmltools)
|
||||||
|
library(DiagrammeR)
|
||||||
|
library(magrittr)
|
||||||
|
library(plotly)
|
||||||
|
library(shiny)
|
||||||
|
library(googleway)
|
||||||
|
library(Rgraphviz)
|
||||||
|
|
||||||
|
addResourcePath("js", "./www/js")
|
||||||
|
|
||||||
|
source('Parses.R')
|
||||||
|
|
||||||
|
# shinyInput <- function(FUN, len, id, ...) {
|
||||||
|
# inputs <- character(len)
|
||||||
|
# for (i in seq_len(len)) {
|
||||||
|
# inputs[i] <- as.character(FUN(paste0(id, i), ...))
|
||||||
|
# }
|
||||||
|
# inputs
|
||||||
|
# }
|
||||||
|
|
||||||
|
ui<-dashboardPage(
|
||||||
|
dashboardHeader(title = "JNCC MESO online"),
|
||||||
|
dashboardSidebar(
|
||||||
|
sidebarMenu(id = "tabs",
|
||||||
|
menuItem("Pressure Test", tabName = "1", icon = icon("align-left", lib = "glyphicon")),
|
||||||
|
menuItem("Bayesian Network", tabName = "2", icon = icon("plug")),
|
||||||
|
menuItem("Habitats", tabName = "3", icon = icon("map")),
|
||||||
|
selectInput(ns("modelSelect"), "Select MESO model", choices=ns("output$selModels"), selected=NULL, multiple=FALSE)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
dashboardBody(
|
||||||
|
tabItems(
|
||||||
|
tabItem(tabName = "1",h4("Pressure Test"),
|
||||||
|
fluidPage(
|
||||||
|
fluidRow(
|
||||||
|
column(width=3,
|
||||||
|
radioButtons(ns("pressure1"), 'Sediment type', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons(ns("pressure2"), 'Seabed type', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons(ns("pressure3"), 'Material extraction', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons(ns("pressure4"), 'Abrasion of seabed', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons(ns("pressure5"), 'Penetration of seabed', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons(ns("pressure6"), 'Siltation', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons(ns("pressure7"), 'Wave exposure', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons(ns("pressure8"), 'Suspended sediment', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons(ns("pressure9"), 'Generic contamination', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons(ns("pressure10"), 'Deoxygenation', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons(ns("pressure11"), 'Removal of target species', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
actionButton(ns("calcAB"), "Calc")
|
||||||
|
),
|
||||||
|
column(width=9,
|
||||||
|
plotlyOutput(ns("layer1"), height="300px") %>% withSpinner(),
|
||||||
|
plotlyOutput(ns("layer2"), height="300px") %>% withSpinner(),
|
||||||
|
plotlyOutput(ns("layer3"), height="300px") %>% withSpinner()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
tabItem(tabName = "2",h4("Bayesian Network"),
|
||||||
|
fluidPage(
|
||||||
|
fluidRow(
|
||||||
|
plotOutput(ns("bbnGraphPlot"))
|
||||||
|
),
|
||||||
|
fluidRow(
|
||||||
|
column(
|
||||||
|
width=6,
|
||||||
|
DT::dataTableOutput(ns('nodeTable'))
|
||||||
|
),
|
||||||
|
column(
|
||||||
|
width=6,
|
||||||
|
DT::dataTableOutput(ns('edgeTable'))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
tabItem(tabName = "3",h4("Habitats"),
|
||||||
|
fluidPage(
|
||||||
|
google_mapOutput(outputId = "map", width = "100%", height = "400px")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
server <- function(input, output, session) {
|
||||||
|
#SERVER Constants
|
||||||
|
|
||||||
|
print('Loading data')
|
||||||
|
|
||||||
|
set_key("AIzaSyAw8_btgGN1drf8qhCxNcotP6r11qEXA_M")
|
||||||
|
dataStorage <- 'data/'
|
||||||
|
|
||||||
|
models<-NULL
|
||||||
|
selectedModel <- NULL
|
||||||
|
|
||||||
|
availableModels <- function() return(models)
|
||||||
|
|
||||||
|
observeEvent(input$modelSelect, {
|
||||||
|
selectedModel <<- match(input$modelSelect, models)
|
||||||
|
})
|
||||||
|
|
||||||
|
output$map <- renderGoogle_map({
|
||||||
|
google_map(location = c(0, 55), zoom = 10)
|
||||||
|
})
|
||||||
|
|
||||||
|
#parse on load sheets in the input sheet folder
|
||||||
|
|
||||||
|
modelList <- list()
|
||||||
|
fileList <- list.files(dataStorage, pattern='.xlsx')
|
||||||
|
|
||||||
|
print(fileList)
|
||||||
|
|
||||||
|
for (idx in 1:length(fileList)) {
|
||||||
|
tmp <- parseSheets(fileList[idx], plot=FALSE)
|
||||||
|
|
||||||
|
if (!is.null(tmp)) {
|
||||||
|
modelList[[cnt]] <- tmp
|
||||||
|
models <<- c(models, substring(fileList[idx], start=1, stop=nchar(fileList[idx])-5))
|
||||||
|
print(paste('Model file successfully loaded', fileList[idx]))
|
||||||
|
cnt=cnt+1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output$nodeTable <- DT::renderDataTable(modelList[[selectedModel]]$pressEcoServMap$nodes,
|
||||||
|
selection = 'single',options = list(searching = FALSE,pageLength = 10),server = TRUE, escape = FALSE,rownames= TRUE)
|
||||||
|
|
||||||
|
output$edgeTable <- DT::renderDataTable(modelList[[selectedModel]]$pressEcoServMap$edges,
|
||||||
|
selection = 'single',options = list(searching = FALSE,pageLength = 10),server = TRUE, escape = FALSE,rownames= TRUE)
|
||||||
|
|
||||||
|
|
||||||
|
output$bbnGraphPlot <- renderPlot({
|
||||||
|
graphviz.plot(modelList[[selectedModel]]$p_es$net)
|
||||||
|
})
|
||||||
|
|
||||||
|
output$layer1 <- renderPlotly({
|
||||||
|
calcLikelihood(plot=TRUE)
|
||||||
|
})
|
||||||
|
|
||||||
|
output$layer2 <- renderPlotly({
|
||||||
|
calcLikelihood(plot=TRUE)
|
||||||
|
})
|
||||||
|
|
||||||
|
output$layer3 <- renderPlotly({
|
||||||
|
calcLikelihood(plot=TRUE)
|
||||||
|
})
|
||||||
|
|
||||||
|
# TaskRow <- eventReactive(input$select_button,{
|
||||||
|
# taskList[SelectedRow(),2:ncol(taskList)]
|
||||||
|
# })
|
||||||
|
#
|
||||||
|
# points <- eventReactive(input$recalc, {
|
||||||
|
# cbind(rnorm(40) * 2 + 13, rnorm(40) + 48)
|
||||||
|
# }, ignoreNULL = FALSE)
|
||||||
|
#
|
||||||
|
# cities <- read.csv(textConnection("
|
||||||
|
# City,Lat,Long,Pop
|
||||||
|
# Boston,42.3601,41.0589,645966
|
||||||
|
# Hartford,41.7627,42.6743,125017
|
||||||
|
# New York City,40.7127,44.0059,8406000
|
||||||
|
# Philadelphia,39.9500,45.1667,1553000
|
||||||
|
# Pittsburgh,40.4397,39.9764,305841
|
||||||
|
# Providence,41.8236,41.4222,177994
|
||||||
|
# "))
|
||||||
|
|
||||||
|
# output$mymap <- renderLeaflet({
|
||||||
|
# leaflet(cities) %>% addTiles() %>%
|
||||||
|
# addCircles(lng = ~Long, lat = ~Lat, weight = 1,
|
||||||
|
# radius = ~sqrt(Pop) * 30, popup = ~City
|
||||||
|
# )
|
||||||
|
# })
|
||||||
|
|
||||||
|
# output$mymap1 <- renderUI({
|
||||||
|
# require(maptools)
|
||||||
|
#
|
||||||
|
# data(meuse)
|
||||||
|
# coordinates(meuse) = ~x+y
|
||||||
|
# proj4string(meuse) <- CRS("+init=epsg:28992")
|
||||||
|
#
|
||||||
|
# data(meuse.grid)
|
||||||
|
# coordinates(meuse.grid)<-c('x','y')
|
||||||
|
# meuse.grid<-as(meuse.grid,'SpatialPixelsDataFrame')
|
||||||
|
# im<-as.image.SpatialGridDataFrame(meuse.grid['dist'])
|
||||||
|
# cl<-ContourLines2SLDF(contourLines(im))
|
||||||
|
# str(cl)
|
||||||
|
# proj4string(cl) <- CRS('+init=epsg:28992')
|
||||||
|
#
|
||||||
|
# #m <- plotGoogleMaps(meuse, filename = 'myMap1.html', openMap = FALSE, streetViewControl = TRUE)
|
||||||
|
#
|
||||||
|
# # Combine point and line data
|
||||||
|
# m<-plotGoogleMaps(meuse, mapTypeId='TERRAIN', openMap = FALSE)
|
||||||
|
# #mapMeusePoints<- plotGoogleMaps(cl, mapTypeId='TERRAIN', openMap = FALSE)
|
||||||
|
# comboMap<- plotGoogleMaps(cl,add=TRUE, previousMap=m, openMap = FALSE, layerName='Lines')
|
||||||
|
# finalMap<- plotGoogleMaps(comboMap, filename = '/home/spegg/R projects/draw/www/myMap1.htm', openMap = FALSE)
|
||||||
|
#
|
||||||
|
# tags$iframe(
|
||||||
|
# srcdoc = paste(readLines('/home/spegg/R projects/draw/www/myMap1.htm'), collapse = '\n'),
|
||||||
|
# width = "100%",
|
||||||
|
# height = "600px"
|
||||||
|
# )
|
||||||
|
# })
|
||||||
|
#
|
||||||
|
# output$popup <- renderUI({
|
||||||
|
# bsModal("taskModal", paste0("Task information for: ",SelectedRow()), "", size = "large",
|
||||||
|
# column(12,
|
||||||
|
# DT::renderDataTable(TaskRow())
|
||||||
|
# ),
|
||||||
|
# column(6,
|
||||||
|
# actionButton("openTask", "Open Task")
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
# })
|
||||||
|
}
|
||||||
|
|
||||||
|
shinyApp(ui('JNCC'), function(...) {callModule(server, 'JNCC')})
|
||||||
328
Parses.R
Normal file
328
Parses.R
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
|
||||||
|
modules::import(openxlsx)
|
||||||
|
modules::import(bnlearn)
|
||||||
|
modules::import(stringr)
|
||||||
|
modules::import(graph)
|
||||||
|
modules::import(ggplot2)
|
||||||
|
modules::import(stats)
|
||||||
|
modules::import(plotly)
|
||||||
|
modules::import(utils)
|
||||||
|
|
||||||
|
|
||||||
|
#Improvements needed: make the selection of first row/column of nodes programmatic
|
||||||
|
FIRST_NODE_COL <- 3
|
||||||
|
|
||||||
|
mappings <- c('TestScenario', 'Map_P_BA', 'Map_BA_OP', 'Map_OP_ES')
|
||||||
|
nodeTypes <- c('Input.Nodes', 'Internal.Nodes', 'Published.Nodes')
|
||||||
|
states <- c('impact', 'confidence', 'growth', 'recovery')
|
||||||
|
refs <-c(1:length(mappings))
|
||||||
|
|
||||||
|
setEmpties <- function(val) {
|
||||||
|
if (is.na(val)) return(0) else return(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
readXL <- function(fName, sheetN, startRow=1) {
|
||||||
|
xl <- read.xlsx(fName, sheet = sheetN, startRow) #, rowNames = import)
|
||||||
|
return(data.frame(xl, stringsAsFactors = FALSE, row.names = NULL))
|
||||||
|
}
|
||||||
|
|
||||||
|
delNA <- function(vec) {
|
||||||
|
return(vec[!is.na(vec)])
|
||||||
|
}
|
||||||
|
|
||||||
|
parseScenario <- function(press, prefix = 'p') {
|
||||||
|
pressNames <- colnames(press)[2:length(colnames(press))]
|
||||||
|
coefs <- matrix(data=NA, nrow=length(pressNames), ncol=2, dimnames=list(NULL, c('growth', 'confidence')))
|
||||||
|
for (col in 2:ncol(press)) {
|
||||||
|
coefs[col-1,] <- as.numeric(split(press[1, col]))[match(c('growth', 'confidence'), states)]
|
||||||
|
}
|
||||||
|
press[is.na(press)] <- 0
|
||||||
|
if (sum(duplicated(pressNames))>0) {
|
||||||
|
cat('Duplicated pressure node names found')
|
||||||
|
print(pressNodes[duplicated(pressNames)])
|
||||||
|
}
|
||||||
|
|
||||||
|
return(list(
|
||||||
|
timeSeq=press,
|
||||||
|
nodes=data.frame(name = pressNames,
|
||||||
|
code=paste0(prefix, seq(1:length(pressNames))),
|
||||||
|
growth = coefs[,'growth'],
|
||||||
|
confidence=coefs[,'confidence'],
|
||||||
|
stringsAsFactors = FALSE),
|
||||||
|
edges=data.frame(input=NULL, output=NULL, impact=NULL)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
getInitial <- function(string, letter) {
|
||||||
|
return(tolower(substr(string, start=1, stop=1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
split <- function(cell) {
|
||||||
|
params <- unlist(strsplit(cell, ','))
|
||||||
|
values <- rep(0, length(states))
|
||||||
|
|
||||||
|
for (n in 1:length(params)) {
|
||||||
|
kvp <- unlist(strsplit(params[n], '='))
|
||||||
|
ref <- match(getInitial(trimws(kvp[1])), getInitial(states))
|
||||||
|
if ((ref>0) & (ref<=length(values))) {
|
||||||
|
values[ref] <- kvp[2]
|
||||||
|
} else {
|
||||||
|
print(paste('Unrecognised parameter(s):',params[n]))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return(values)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanTitles <- function(titleV) {
|
||||||
|
return(str_replace_all(titleV, c(' ' = '.', '-' = '')))
|
||||||
|
}
|
||||||
|
|
||||||
|
getOutNodes <- function(codes, codeList) {
|
||||||
|
v <- vector(mode='logical', length=length(codes))
|
||||||
|
for (idx in 1:length(codes)) {
|
||||||
|
v[idx] <- (sum(startsWith(codes[idx], codeList))>0)
|
||||||
|
}
|
||||||
|
return(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
buildGraph <- function(model, desc) {
|
||||||
|
|
||||||
|
#model contains the following
|
||||||
|
# node table, edge table
|
||||||
|
|
||||||
|
#descriptor (desc) contains:
|
||||||
|
#inputCode - the top layer of the model
|
||||||
|
#outputCodes - all subsequent layers to be included in the model
|
||||||
|
|
||||||
|
inputNodes <- model$nodes$code[which(startsWith(model$nodes$code, desc$inputCode))]
|
||||||
|
inputText <- paste0("[", inputNodes, "]", collapse ="")
|
||||||
|
|
||||||
|
#do the internal nodes
|
||||||
|
edges <- ""
|
||||||
|
|
||||||
|
outNodes <- model$nodes$code[getOutNodes(model$nodes$code, desc$outputCodes)]
|
||||||
|
outDist <- vector(mode="list", length=length(outNodes))
|
||||||
|
|
||||||
|
for (idx in 1:length(outNodes)) {
|
||||||
|
nodeRef <- match(outNodes[idx], model$nodes$code)
|
||||||
|
|
||||||
|
rows <- which(model$edges$output == outNodes[idx])
|
||||||
|
inputsStr <- paste0(model$edges$input[which(model$edges$output == outNodes[idx])], sep=":", collapse="")
|
||||||
|
edges <- paste0(edges, paste0("[", outNodes[idx], "|", substr(inputsStr, start=1, stop=(nchar(inputsStr)-1)), "]"))
|
||||||
|
|
||||||
|
#Make the coefficient of the distribution
|
||||||
|
coefVal <- setNames(c(model$nodes$growth[nodeRef], model$edges$impact[rows]),
|
||||||
|
c("(Intercept)", model$edges$input[rows])
|
||||||
|
)
|
||||||
|
#str(coefVal)
|
||||||
|
outDist[[idx]] <- list(coef = coefVal,
|
||||||
|
sd = model$nodes$confidence[nodeRef])
|
||||||
|
}
|
||||||
|
|
||||||
|
print('about to build network')
|
||||||
|
|
||||||
|
net <- model2network(paste0(inputText, edges))
|
||||||
|
|
||||||
|
print('network build successful')
|
||||||
|
|
||||||
|
inDist <- vector(mode="list", length=length(inputNodes))
|
||||||
|
|
||||||
|
for (idx in 1:length(inputNodes)) {
|
||||||
|
inRef <- match(inputNodes[idx], model$nodes$code)
|
||||||
|
coefVal <- setNames(model$nodes$growth[inRef], "(Intercept)")
|
||||||
|
inDist[[idx]] <- list(coef = coefVal, sd = model$nodes$confidence[inRef])
|
||||||
|
}
|
||||||
|
|
||||||
|
allDists = as.list(setNames(c(inDist, outDist), c(inputNodes, outNodes)))
|
||||||
|
cfit = custom.fit(net, allDists)
|
||||||
|
|
||||||
|
cat('about to calculate sample distributions')
|
||||||
|
print(outNodes)
|
||||||
|
|
||||||
|
sampleDists <- cpdist(cfit, nodes = outNodes, evidence = TRUE, n = 10000, method = "lw")
|
||||||
|
summDists <- summary(sampleDists)
|
||||||
|
#stdDev <- sd(sampleDists)
|
||||||
|
|
||||||
|
print('sample distribution build successful')
|
||||||
|
|
||||||
|
model$edges$input <- model$nodes$name[match(model$edges$input, model$nodes$code)]
|
||||||
|
model$edges$output <- model$nodes$name[match(model$edges$output, model$nodes$code)]
|
||||||
|
|
||||||
|
return(
|
||||||
|
list(
|
||||||
|
nodes = model$nodes,
|
||||||
|
edges = model$edges,
|
||||||
|
net = net,
|
||||||
|
cfit = cfit,
|
||||||
|
allDists = allDists,
|
||||||
|
summDists = summDists
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getValidNodes <- function(mapping, prevOutputs, prefix) {
|
||||||
|
|
||||||
|
#Find row id for input nodes, internal and published
|
||||||
|
inputNodes <- mapping[2:nrow(mapping),1]
|
||||||
|
|
||||||
|
#check that all input nodes are in the previous table
|
||||||
|
inputNodes <- delNA(mapping[mapping[,"Node.Type"] == 'input', "Nodes"])
|
||||||
|
if (length(inputNodes)>0) {
|
||||||
|
if (sum(inputNodes %in% prevOutputs$name)<length(inputNodes)) {
|
||||||
|
cat('Missing entries for input nodes in previous output columns')
|
||||||
|
print(inputNodes[!inputNodes %in% prevOutputs$name])
|
||||||
|
}
|
||||||
|
} else print('Invalid sheet - table must have at least one input row containing names from previous table')
|
||||||
|
|
||||||
|
|
||||||
|
#Check the row headings concur with previous names
|
||||||
|
validInputs <- delNA(inputNodes[which(unique(inputNodes) %in% prevOutputs$name)])
|
||||||
|
if (length(validInputs)==0) print('Invalid sheet - table must have at least one input row containing names from previous table')
|
||||||
|
|
||||||
|
|
||||||
|
inputInts <- delNA(inputNodes[mapping$Node.Type!='link'])
|
||||||
|
|
||||||
|
if (sum(duplicated(inputInts))>0) {
|
||||||
|
cat('Duplicated input node names found')
|
||||||
|
print(inputNodes[duplicated(inputNodes)])
|
||||||
|
}
|
||||||
|
|
||||||
|
outNodes <- delNA(colnames(mapping)[FIRST_NODE_COL:ncol(mapping)])
|
||||||
|
if (sum(duplicated(outNodes))>0) {
|
||||||
|
cat('Duplicated output node names found')
|
||||||
|
print(outNodes[duplicated(outNodes)])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#check that all internal nodes are in the columns
|
||||||
|
intNodes <- delNA(mapping[mapping[,"Node.Type"] == 'internal', "Nodes"])
|
||||||
|
if (length(intNodes)>0) {
|
||||||
|
if (sum(intNodes %in% outNodes)<length(intNodes)) {
|
||||||
|
cat('Missing entries for internal nodes in output columns')
|
||||||
|
print(intNodes[!intNodes %in% outNodes])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coefs <- matrix(data=NA, nrow=length(outNodes), ncol=2, dimnames=list(NULL, c('growth', 'confidence')))
|
||||||
|
for (idx in 1:length(outNodes)) {
|
||||||
|
col <- match(outNodes[idx], colnames(mapping))
|
||||||
|
coefs[idx,] <- as.numeric(split(mapping[1, col]))[match(c('growth', 'confidence'), states)]
|
||||||
|
}
|
||||||
|
|
||||||
|
return(data.frame(
|
||||||
|
code=c(prevOutputs$code, paste0(prefix, seq(1:length(outNodes)))),
|
||||||
|
name=c(prevOutputs$name, outNodes),
|
||||||
|
growth=c(prevOutputs$growth, coefs[,"growth"]),
|
||||||
|
confidence=c(prevOutputs$confidence, coefs[,"confidence"]),
|
||||||
|
stringsAsFactors=FALSE
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
getCode <- function(name, nodeDF) {
|
||||||
|
nodeDF$code[match(name, nodeDF$name)]
|
||||||
|
}
|
||||||
|
|
||||||
|
getValidEdges <- function(mapping, nodeDF, prevEdge=NULL, prefix) {
|
||||||
|
str(nodeDF)
|
||||||
|
edgeCols <- c('inputNode', 'outputNode', 'impact')
|
||||||
|
edgeM <- matrix(data=NA, nrow=0, ncol=length(edgeCols), dimnames=list(NULL, edgeCols))
|
||||||
|
|
||||||
|
#to start let just get the statements and print them out....
|
||||||
|
for (col in FIRST_NODE_COL:ncol(mapping)) {
|
||||||
|
count=0
|
||||||
|
|
||||||
|
for (row in 2:nrow(mapping)) {
|
||||||
|
|
||||||
|
if (!is.na(mapping[row, col])) {
|
||||||
|
edgeM <- rbind(edgeM,
|
||||||
|
c(getCode(mapping[row, 1], nodeDF),
|
||||||
|
getCode(colnames(mapping)[col], nodeDF),
|
||||||
|
split(mapping[row,col])[match('impact', states)]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
count=count+1
|
||||||
|
}
|
||||||
|
#if (count==0) print(paste('No edges found for output', colnames(mapping)[col]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is.null(prevEdge)) return (
|
||||||
|
data.frame(
|
||||||
|
input = edgeM[,"inputNode"],
|
||||||
|
output = edgeM[,"outputNode"],
|
||||||
|
impact = as.numeric(edgeM[,"impact"]),
|
||||||
|
stringsAsFactors = FALSE
|
||||||
|
)
|
||||||
|
) else return (
|
||||||
|
data.frame(
|
||||||
|
input = c(prevEdge$input, edgeM[,"inputNode"]),
|
||||||
|
output = c(prevEdge$output, edgeM[,"outputNode"]),
|
||||||
|
impact = c(prevEdge$impact, as.numeric(edgeM[,"impact"])),
|
||||||
|
stringsAsFactors = FALSE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
parseMapping <- function(mapping, prevOutputs, prefix) {
|
||||||
|
|
||||||
|
mapping <- mapping[,-1]
|
||||||
|
mapping[,1] <- cleanTitles(mapping[,1])
|
||||||
|
|
||||||
|
nodeDF <- getValidNodes(mapping, prevOutputs$nodes, prefix)
|
||||||
|
edgeDF <- getValidEdges(mapping, nodeDF, prevEdge=prevOutputs$edges, prefix)
|
||||||
|
|
||||||
|
return(list(
|
||||||
|
#New structure
|
||||||
|
nodes=nodeDF,
|
||||||
|
edges=edgeDF
|
||||||
|
))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
parseSheet <- function(fName) {
|
||||||
|
#get sheet names
|
||||||
|
|
||||||
|
print(paste('starting sheet load', fName))
|
||||||
|
|
||||||
|
if (file.exists(fName)) {
|
||||||
|
names <- openxlsx::getSheetNames(fName)
|
||||||
|
|
||||||
|
if (length(names)>0) {
|
||||||
|
|
||||||
|
sheets <- sort(delNA(match(names, mappings)))
|
||||||
|
|
||||||
|
cat('starting sheet parse')
|
||||||
|
print(sheets)
|
||||||
|
|
||||||
|
if (sum(sheets==refs)==length(refs)) {
|
||||||
|
#read all mapping tables
|
||||||
|
scenario <- parseScenario(readXL(fName,mappings[1], startRow=1), prefix='p')
|
||||||
|
p_ba <- parseMapping(readXL(fName,mappings[2], startRow=1), scenario, prefix='ba')
|
||||||
|
p_op <- parseMapping(readXL(fName,mappings[3], startRow=1), p_ba, prefix='op')
|
||||||
|
p_es <- parseMapping(readXL(fName,mappings[4], startRow=1), p_op, prefix='es')
|
||||||
|
|
||||||
|
print('building graphs')
|
||||||
|
|
||||||
|
p_baNet <- buildGraph(p_ba, desc=list(inputCode='p', outputCodes='ba'))
|
||||||
|
p_opNet <- buildGraph(p_op, desc=list(inputCode='p', outputCodes=c('ba', 'op')))
|
||||||
|
p_esNet <- buildGraph(p_es, desc=list(inputCode='p', outputCodes=c('ba', 'op', 'es')))
|
||||||
|
|
||||||
|
print('sheet load completed')
|
||||||
|
return(
|
||||||
|
list(
|
||||||
|
pressBioAss = p_baNet,
|
||||||
|
pressOpProc = p_opNet,
|
||||||
|
pressEcoServ = p_esNet
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
print(paste('Sheets found include', mappings[sheets]))
|
||||||
|
cat('Missing sheets are:')
|
||||||
|
print(refs[-sheets])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
267
app.R
Normal file
267
app.R
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
modules::import(DT)
|
||||||
|
modules::import(shiny)
|
||||||
|
modules::import(shinyBS)
|
||||||
|
modules::import(shinyjs)
|
||||||
|
modules::import(shinydashboard)
|
||||||
|
modules::import(htmltools)
|
||||||
|
modules::import(DiagrammeR)
|
||||||
|
modules::import(magrittr)
|
||||||
|
modules::import(plotly)
|
||||||
|
modules::import(kableExtra)
|
||||||
|
modules::import(Rgraphviz)
|
||||||
|
modules::import(knitr)
|
||||||
|
modules::import(shinycssloaders)
|
||||||
|
modules::import(googleway)
|
||||||
|
modules::import(Rgraphviz)
|
||||||
|
modules::import(bnlearn)
|
||||||
|
|
||||||
|
parser <- modules::use('Parses.R')
|
||||||
|
|
||||||
|
layers <- c("Pressures to Bio-Assemblages", "Bio-Assemblages to Output Processes", "Output Processes to Eco-system services")
|
||||||
|
transitions <- c("Pressures to Bio-Assemblages", "Pressures to Output Processes", "Pressures to Eco-system services")
|
||||||
|
addResourcePath("js", "./www/js")
|
||||||
|
|
||||||
|
ui<-dashboardPage(
|
||||||
|
dashboardHeader(title = "JNCC MESO online"),
|
||||||
|
dashboardSidebar(
|
||||||
|
sidebarMenu(id = "tabs",
|
||||||
|
menuItem("Pressure Test", tabName = "1", icon = icon("arrow-down")),
|
||||||
|
menuItem("Bayesian Network", tabName = "2", icon = icon("atom")),
|
||||||
|
menuItem("Habitats", tabName = "3", icon = icon("atlas")),
|
||||||
|
selectInput("modelSelect", "Select MESO model", choices=c(""), selected=NULL, multiple=FALSE),
|
||||||
|
selectInput("layerSelect", "Select Transition",
|
||||||
|
choices=transitions,
|
||||||
|
selected=NULL, multiple=FALSE)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
dashboardBody(
|
||||||
|
tabItems(
|
||||||
|
tabItem(tabName = "1",
|
||||||
|
fluidRow(
|
||||||
|
column(width=2,
|
||||||
|
h4('Pressure Test'),
|
||||||
|
radioButtons("pressure1", 'Sediment type', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons("pressure2", 'Seabed type', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons("pressure3", 'Material extraction', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons("pressure4", 'Abrasion of seabed', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons("pressure5", 'Penetration of seabed', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons("pressure6", 'Siltation', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons("pressure7", 'Wave exposure', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons("pressure8", 'Suspended sediment', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons("pressure9", 'Generic contamination', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons("pressure10", 'Deoxygenation', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
radioButtons("pressure11", 'Removal of target species', choices=c('On', 'Off'), inline=TRUE),
|
||||||
|
actionButton("calcAB", "Calc")
|
||||||
|
),
|
||||||
|
column(width=10,
|
||||||
|
h4('Effect on bio-assemblage'),
|
||||||
|
plotlyOutput("layer1", height="270px") %>% withSpinner(),
|
||||||
|
h4('Effect on Output Processes'),
|
||||||
|
plotlyOutput("layer2", height="270px") %>% withSpinner(),
|
||||||
|
h4('Effect on Eco-system services'),
|
||||||
|
plotlyOutput("layer3", height="270px") %>% withSpinner()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
tabItem(tabName = "2",h4("Bayesian Network"),
|
||||||
|
fluidPage(
|
||||||
|
fluidRow(
|
||||||
|
plotOutput("bbnGraphPlot")
|
||||||
|
),
|
||||||
|
fluidRow(
|
||||||
|
column(
|
||||||
|
width=6,
|
||||||
|
h4('Ecoservice nodes'),
|
||||||
|
DT::dataTableOutput('nodeTable')
|
||||||
|
),
|
||||||
|
column(
|
||||||
|
width=6,
|
||||||
|
h4('Ecoservice influences'),
|
||||||
|
DT::dataTableOutput('edgeTable')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
tabItem(tabName = "3",h4("Habitats"),
|
||||||
|
fluidPage(
|
||||||
|
google_mapOutput(outputId = "map", width = "100%", height = "750px")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
server <- function(input, output, session) {
|
||||||
|
#SERVER Constants
|
||||||
|
|
||||||
|
print('Loading data')
|
||||||
|
|
||||||
|
set_key("AIzaSyAw8_btgGN1drf8qhCxNcotP6r11qEXA_M")
|
||||||
|
dataStorage <- 'data/'
|
||||||
|
|
||||||
|
models<-NULL
|
||||||
|
|
||||||
|
getAvailableModels <- function() {
|
||||||
|
fileList <- list.files(dataStorage, pattern='.xlsx')
|
||||||
|
|
||||||
|
print(fileList)
|
||||||
|
modelList <- list()
|
||||||
|
cnt<-1
|
||||||
|
|
||||||
|
for (idx in 1:length(fileList)) {
|
||||||
|
print(paste('attempting to load', paste0(dataStorage, fileList[idx])))
|
||||||
|
tmp <- parser$parseSheet(paste0(dataStorage, fileList[idx]))
|
||||||
|
|
||||||
|
if (!is.null(tmp)) {
|
||||||
|
modelList[[cnt]] <- tmp
|
||||||
|
|
||||||
|
#tidy up the list for displaying
|
||||||
|
|
||||||
|
models <<- c(models, substr(fileList[idx], 1, (nchar(fileList[idx])-5)))
|
||||||
|
print(paste('Model file successfully loaded', fileList[idx]))
|
||||||
|
cnt=cnt+1
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSelectInput(session, "modelSelect", choices=models)
|
||||||
|
|
||||||
|
return(modelList)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.selections <- reactiveValues(model=1, layer=1)
|
||||||
|
|
||||||
|
#parse on load sheets in the input sheet folder
|
||||||
|
modelList <- getAvailableModels()
|
||||||
|
|
||||||
|
calcLikelihood <- function(layer) {
|
||||||
|
|
||||||
|
isolate({
|
||||||
|
if (layer==1) layerStr='ba' else if (layer==2) layerStr='op' else layerStr ='es'
|
||||||
|
nodeList <- modelList[[.selections$model]][[.selections$layer]]$nodes
|
||||||
|
str(nodeList)
|
||||||
|
nodeNames <- nodeList$name[startsWith(nodeList$code, layerStr)]
|
||||||
|
mean = runif(length(nodeNames), min=-1, max=1)
|
||||||
|
sd = runif(length(nodeNames), min=-0.25, max=0.25)
|
||||||
|
|
||||||
|
df <- data.frame(
|
||||||
|
nodeNames = nodeNames,
|
||||||
|
range = c((mean - (3*sd)), (mean - (2*sd)), (mean - sd), mean,
|
||||||
|
(mean + sd), (mean + (2*sd)), (mean + (3*sd))),
|
||||||
|
stringsAsFactors=FALSE
|
||||||
|
)
|
||||||
|
print(df)
|
||||||
|
})
|
||||||
|
return(
|
||||||
|
df
|
||||||
|
)
|
||||||
|
# isolate({
|
||||||
|
#
|
||||||
|
# if (layer==1) layerStr='ba' else if (layer==2) layerStr='op' else if (layer==3) layerStr='es'
|
||||||
|
#
|
||||||
|
# layerRange <- which(startsWith(modelList[[.selections$model]][[layer]]$nodes, layerStr))
|
||||||
|
# distList <- modelList[[.selections$model]][[layer]]$summDist[,layerRange]
|
||||||
|
# nodeNames <- modelList[[.selections$model]][[layer]]$nodes$name[layerRange]
|
||||||
|
#
|
||||||
|
# }
|
||||||
|
|
||||||
|
# print(paste('Length of layer & node names',layer, length(nodeNames)))
|
||||||
|
#
|
||||||
|
# distList <- modelList[[.selections$model]][[layer]]$summDist
|
||||||
|
# colNames <- c('min', 'q1', 'q1', 'mean', 'q3', 'q3', 'max')
|
||||||
|
# distM <- matrix(data=NA, nrow=ncol(distList), ncol=length(colNames))
|
||||||
|
#
|
||||||
|
# print(paste('Length of distributions',nrow(distM)))
|
||||||
|
|
||||||
|
# for (col in 1:ncol(distList)) {
|
||||||
|
# valsAsStrs <- unlist(strsplit(distList[,col], ":"))
|
||||||
|
# valIdxs <- seq(from=2, to=length(valsAsStrs), by=2)
|
||||||
|
# distVals <- as.numeric(valsAsStrs[valIdxs])
|
||||||
|
# distM[col,] <- c(distVals[1], distVals[2], distVals[2], distVals[4], distVals[5], distVals[5], distVals[6])
|
||||||
|
# }
|
||||||
|
# })
|
||||||
|
#
|
||||||
|
# df <- data.frame(
|
||||||
|
# nodeNames = nodeNames,
|
||||||
|
# dist = distM,
|
||||||
|
# stringsAsFactors=FALSE
|
||||||
|
# )
|
||||||
|
# print(df)
|
||||||
|
#
|
||||||
|
# return(
|
||||||
|
# df
|
||||||
|
# )
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.likelihoods <-reactiveValues(
|
||||||
|
p_ba = calcLikelihood(1),
|
||||||
|
ba_os = calcLikelihood(2),
|
||||||
|
os_es = calcLikelihood(3)
|
||||||
|
)
|
||||||
|
|
||||||
|
observeEvent(input$modelSelect, {
|
||||||
|
.selections$model <<- match(input$modelSelect, models)
|
||||||
|
#print(.selections$model)
|
||||||
|
})
|
||||||
|
|
||||||
|
observeEvent(input$layerSelect, {
|
||||||
|
.selections$layer <<- match(input$layerSelect, transitions)
|
||||||
|
#print(.selections$layer)
|
||||||
|
})
|
||||||
|
|
||||||
|
observeEvent(input$calcAB, {
|
||||||
|
#print(paste('Action button pressed', input$calcAB))
|
||||||
|
|
||||||
|
.likelihoods$p_ba <<- calcLikelihood(1)
|
||||||
|
.likelihoods$ba_os <<- calcLikelihood(2)
|
||||||
|
.likelihoods$os_es <<- calcLikelihood(3)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
output$map <- renderGoogle_map({
|
||||||
|
google_map(location = c(55, 0), zoom = 7)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
output$nodeTable <- DT::renderDataTable(
|
||||||
|
|
||||||
|
modelList[[.selections$model]][[.selections$layer]]$nodes,
|
||||||
|
selection = 'single',options = list(searching = TRUE, pageLength = 10),server = TRUE, escape = FALSE,rownames= TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
output$edgeTable <- DT::renderDataTable(
|
||||||
|
|
||||||
|
modelList[[.selections$model]][[.selections$layer]]$edges,
|
||||||
|
selection = 'single',options = list(searching = TRUE, pageLength = 10),server = TRUE, escape = FALSE,rownames= TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
output$bbnGraphPlot <- renderPlot({
|
||||||
|
graphviz.plot(modelList[[.selections$model]][[.selections$layer]]$net)
|
||||||
|
})
|
||||||
|
|
||||||
|
output$layer1 <- renderPlotly({
|
||||||
|
plot_ly(.likelihoods$p_ba, y = ~range, color = ~nodeNames, type = "box")
|
||||||
|
})
|
||||||
|
|
||||||
|
output$layer2 <- renderPlotly({
|
||||||
|
#print(.likelihoods)
|
||||||
|
|
||||||
|
if (.selections$layer>1) {
|
||||||
|
plot_ly(.likelihoods$ba_os, y = ~range, color = ~nodeNames, type = "box")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
output$layer3 <- renderPlotly({
|
||||||
|
|
||||||
|
if (.selections$layer>2) {
|
||||||
|
plot_ly(.likelihoods$os_es, y = ~range, color = ~nodeNames, type = "box")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
shinyApp(ui, server)
|
||||||
BIN
data/BaselineTestHabitat.xlsx
Normal file
BIN
data/BaselineTestHabitat.xlsx
Normal file
Binary file not shown.
BIN
data/WorkingTestHabitat.xlsx
Normal file
BIN
data/WorkingTestHabitat.xlsx
Normal file
Binary file not shown.
9109
www/css/bootstrap.css
vendored
Normal file
9109
www/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
387
www/css/joint.css
Normal file
387
www/css/joint.css
Normal file
File diff suppressed because one or more lines are too long
1920
www/js/backbone.js
Normal file
1920
www/js/backbone.js
Normal file
File diff suppressed because it is too large
Load Diff
204
www/js/custom.js
Normal file
204
www/js/custom.js
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
|
||||||
|
var avsdev = {
|
||||||
|
pivot: {
|
||||||
|
dataFile: null,
|
||||||
|
rowKey: 25,
|
||||||
|
colKey: 400,
|
||||||
|
active: false
|
||||||
|
},
|
||||||
|
geoView: {
|
||||||
|
active: false,
|
||||||
|
firstRun: true
|
||||||
|
},
|
||||||
|
cc: {
|
||||||
|
"DZA":"DZA - Algeria","AGO":"AGO - Angola","BEN":"BEN - Benin","BWA":"BWA - Botswana","BFA":"BFA - Burkina Faso","BDI":"BDI - Burundi","CMR":"CMR - Cameroon","CPV":"CPV - Cape Verde","CAF":"CAF - Central African Republic","TCD":"TCD - Chad","COM":"COM - Comoros","COD":"COD - Democratic Republic of the Congo","DJI":"DJI - Djibouti","EGY":"EGY - Egypt","GNQ":"GNQ - Equatorial Guinea","ERI":"ERI - Eritrea","ETH":"ETH - Ethiopia","GAB":"GAB - Gabon","GMB":"GMB - Gambia","GHA":"GHA - Ghana","GIN":"GIN - Guinea","GNB":"GNB - Guinea-Bissau","CIV":"CIV - Côte d'Ivoire","KEN":"KEN - Kenya","LSO":"LSO - Lesotho","LBR":"LBR - Liberia","LBY":"LBY - Libya","MDG":"MDG - Madagascar","MWI":"MWI - Malawi","MLI":"MLI - Mali","MRT":"MRT - Mauritania","MUS":"MUS - Mauritius","MAR":"MAR - Morocco","MOZ":"MOZ - Mozambique","NAM":"NAM - Namibia","NER":"NER - Niger","NGA":"NGA - Nigeria","COG":"COG - Republic of the Congo","RWA":"RWA - Rwanda","SHN":"SHN - Saint Helena","STP":"STP - Sao Tome and Principe","SEN":"SEN - Senegal","SYC":"SYC - Seychelles","SLE":"SLE - Sierra Leone","SOM":"SOM - Somalia","ZAF":"ZAF - South Africa","SSD":"SSD - South Sudan","SDN":"SDN - Sudan","SWZ":"SWZ - Swaziland","TZA":"TZA - Tanzania","TGO":"TGO - Togo","TUN":"TUN - Tunisia","UGA":"UGA - Uganda","ESH":"ESH - Western Sahara","ZMB":"ZMB - Zambia","ZWE":"ZWE - Zimbabwe"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function debounce(func, wait, immediate) {
|
||||||
|
var timeout;
|
||||||
|
return function() {
|
||||||
|
var context = this, args = arguments;
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(function() {
|
||||||
|
timeout = null;
|
||||||
|
if (!immediate) func.apply(context, args);
|
||||||
|
}, wait);
|
||||||
|
if (immediate && !timeout) func.apply(context, args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$(document).on('shiny:inputchanged', function(event){
|
||||||
|
|
||||||
|
if (event.name == 'selectView') {
|
||||||
|
avsdev.pivot.active = false;
|
||||||
|
avsdev.geoView.active = false;
|
||||||
|
|
||||||
|
if (event.value == "Geo Image") {
|
||||||
|
avsdev.geoView.active = true;
|
||||||
|
if (avsdev.geoView.firstRun) {
|
||||||
|
zoomGeoView();
|
||||||
|
avsdev.geoView.firstRun = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (event.value == "Pivot Table") {
|
||||||
|
avsdev.pivot.active = true;
|
||||||
|
drawPivot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.name == '.clientdata_output_geoView-mapImage_hidden') {
|
||||||
|
avsdev.geoView.active = !event.value;
|
||||||
|
if (avsdev.geoView.firstRun) {
|
||||||
|
zoomGeoView();
|
||||||
|
avsdev.geoView.firstRun = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// GEO
|
||||||
|
|
||||||
|
|
||||||
|
_zoomGeoView = function(){
|
||||||
|
if (avsdev.geoView.active === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var img = $($("#geoView-mapImage").children("img")[0]);
|
||||||
|
|
||||||
|
if (img.hasClass("zoomed")) {
|
||||||
|
|
||||||
|
if (document.querySelector('#geoView-mapImage img')) {
|
||||||
|
document.querySelector('#geoView-mapImage img').dispatchEvent(new CustomEvent('wheelzoom.destroy'));
|
||||||
|
img.removeClass("zoomed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!img.hasClass("zoomed")) {
|
||||||
|
wheelzoom(img);
|
||||||
|
img.addClass("zoomed");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
zoomGeoView = debounce(function(){ _zoomGeoView() }, 500);
|
||||||
|
|
||||||
|
/*
|
||||||
|
$(document).on('shiny:sessioninitialized', function(event){
|
||||||
|
console.log("shiny:sessioninitialized")
|
||||||
|
zoomGeoView()
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
$(document).on('shiny:value', function(event){
|
||||||
|
if (event.name == 'geoView-mapImage') {
|
||||||
|
zoomGeoView();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// PIVOT
|
||||||
|
|
||||||
|
_drawPivot = function() {
|
||||||
|
if (avsdev.pivot.active === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.getJSON(avsdev.pivot.dataFile, function(data) {
|
||||||
|
data = $(data).each(function(id, v){
|
||||||
|
v.Country = avsdev.cc[v.Country];
|
||||||
|
});
|
||||||
|
data = $.makeArray(data);
|
||||||
|
|
||||||
|
var renderers = $.extend($.pivotUtilities.renderers, $.pivotUtilities.plotly_renderers);
|
||||||
|
renderers = $.extend(renderers, $.pivotUtilities.avsdev_renderers);
|
||||||
|
|
||||||
|
$("#pivot-pivotRender").pivotUI(data, {
|
||||||
|
rows: ["Grid Dist."],
|
||||||
|
cols: ["Pop Density"],
|
||||||
|
aggregatorName: "Sum",
|
||||||
|
vals: ["Population"],
|
||||||
|
renderers: renderers,
|
||||||
|
rendererName: "Coloured Pivot Table",
|
||||||
|
hiddenFromDragDrop: ["Population"],
|
||||||
|
hiddenFromAggregators: ["Grid Dist.", "Country", "Pop Density"],
|
||||||
|
onRefresh: function(config) {
|
||||||
|
var config_copy = JSON.parse(JSON.stringify(config));
|
||||||
|
//delete some values which are functions
|
||||||
|
delete config_copy.aggregators;
|
||||||
|
delete config_copy.renderers;
|
||||||
|
//delete some bulky default values
|
||||||
|
delete config_copy.rendererOptions;
|
||||||
|
delete config_copy.localeStrings;
|
||||||
|
//console.log(JSON.stringify(config_copy, undefined, 2));
|
||||||
|
|
||||||
|
var grid = $("td[data-rowkey]").filter(function() {
|
||||||
|
return $(this).data("rowkey") <= avsdev.pivot.rowKey;
|
||||||
|
});
|
||||||
|
var solar = $("td[data-rowkey]").filter(function() {
|
||||||
|
return $(this).data("rowkey") > avsdev.pivot.rowKey;
|
||||||
|
}).filter(function() {
|
||||||
|
return $(this).data("colkey") <= avsdev.pivot.colKey;
|
||||||
|
});
|
||||||
|
var target = $("td[data-rowkey]").filter(function() {
|
||||||
|
return $(this).data("rowkey") > avsdev.pivot.rowKey;
|
||||||
|
}).filter(function() {
|
||||||
|
return $(this).data("colkey") > avsdev.pivot.colKey;
|
||||||
|
});
|
||||||
|
|
||||||
|
grid.addClass("power-grid");
|
||||||
|
solar.addClass("power-solar");
|
||||||
|
target.addClass("power-target");
|
||||||
|
|
||||||
|
var gridVal = grid.map(function() {
|
||||||
|
return $(this).data("value");
|
||||||
|
}).get().reduce(function(a, b) { return a + b; }, 0);
|
||||||
|
|
||||||
|
var solarVal = solar.map(function() {
|
||||||
|
return $(this).data("value");
|
||||||
|
}).get().reduce(function(a, b) { return a + b; }, 0);
|
||||||
|
|
||||||
|
var miniVal = target.map(function() {
|
||||||
|
return $(this).data("value");
|
||||||
|
}).get().reduce(function(a, b) { return a + b; }, 0);
|
||||||
|
|
||||||
|
var totalVal = gridVal + solarVal + miniVal;
|
||||||
|
var offGrid = parseInt($($("#summary-summaryTable table td")[6]).text())
|
||||||
|
|
||||||
|
$($("#summary-summaryTable table td")[1]).text(Math.round(totalVal - offGrid).toLocaleString('en'));
|
||||||
|
$($("#summary-summaryTable table td")[2]).text(Math.round(offGrid - solarVal - miniVal).toLocaleString('en'));
|
||||||
|
$($("#summary-summaryTable table td")[3]).text(Math.round(solarVal).toLocaleString('en'));
|
||||||
|
$($("#summary-summaryTable table td")[4]).text(Math.round(miniVal).toLocaleString('en'));
|
||||||
|
$($("#summary-summaryTable table td")[5]).text(Math.round(totalVal).toLocaleString('en'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//console.log($("td").find(`[data-colKey > 500]`))
|
||||||
|
//$("#loading-pivot img").toggleClass("collapse");
|
||||||
|
//$("#pivot").toggleClass("collapse");
|
||||||
|
};
|
||||||
|
drawPivot = debounce(function(){ _drawPivot() }, 750);
|
||||||
|
|
||||||
|
Shiny.addCustomMessageHandler("render-pivot",
|
||||||
|
function(message) {
|
||||||
|
avsdev.pivot.dataFile = message.countryTotPath[0] + ".json";
|
||||||
|
drawPivot();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
$(document).on('shiny:inputchanged', function(event){
|
||||||
|
if (event.name == 'control-selectCountry') {
|
||||||
|
drawPivot();
|
||||||
|
} else if (event.name == 'control-selectGrid') {
|
||||||
|
avsdev.pivot.rowKey = event.value;
|
||||||
|
drawPivot();
|
||||||
|
} else if (event.name == 'control-selectPopDensity') {
|
||||||
|
avsdev.pivot.colKey = event.value;
|
||||||
|
drawPivot();
|
||||||
|
} else if (event.name == 'control-selectData') {
|
||||||
|
drawPivot();
|
||||||
|
}
|
||||||
|
});
|
||||||
58
www/js/draw.html
Normal file
58
www/js/draw.html
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
var laydown = {
|
||||||
|
diagram: {
|
||||||
|
dataFile: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var graph = new joint.dia.Graph;
|
||||||
|
|
||||||
|
var paper = new joint.dia.Paper({
|
||||||
|
el: document.getElementById('myholder'),
|
||||||
|
model: graph,
|
||||||
|
width: 600,
|
||||||
|
height: 100,
|
||||||
|
gridSize: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
var rect = new joint.shapes.standard.Rectangle();
|
||||||
|
var rect2 = rect.clone();
|
||||||
|
var link = new joint.shapes.standard.Link();
|
||||||
|
|
||||||
|
drawDiagram = function() {
|
||||||
|
rect.position(100, 30);
|
||||||
|
rect.resize(100, 40);
|
||||||
|
rect.attr({
|
||||||
|
body: {
|
||||||
|
fill: 'blue'
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
text: 'Hello',
|
||||||
|
fill: 'white'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
rect.addTo(graph);
|
||||||
|
|
||||||
|
|
||||||
|
rect2.translate(300, 0);
|
||||||
|
rect2.attr('label/text', 'World!');
|
||||||
|
rect2.addTo(graph);
|
||||||
|
|
||||||
|
|
||||||
|
link.source(rect);
|
||||||
|
link.target(rect2);
|
||||||
|
link.addTo(graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Shiny.addCustomMessageHandler("render-pivot",
|
||||||
|
function(message) {
|
||||||
|
laydown.diagram.dataFile = message.laydown + ".json";
|
||||||
|
drawDiagram();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
$(document).on('shiny:inputchanged', function(event){
|
||||||
|
//TO BE INTEGRATED
|
||||||
|
});
|
||||||
124
www/js/draw.js
Normal file
124
www/js/draw.js
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
var dataFile = null;
|
||||||
|
|
||||||
|
addPort = function() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
drawDiagram = function() {
|
||||||
|
var graph = new joint.dia.Graph();
|
||||||
|
|
||||||
|
var paper = new joint.dia.Paper({
|
||||||
|
el: document.getElementById('laydown'),
|
||||||
|
model: graph,
|
||||||
|
width: 1600,
|
||||||
|
height: 1000,
|
||||||
|
gridSize: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//Declare an array of rectangles - assign icon, name,
|
||||||
|
//for each asset in datafile.assets add a rectangle
|
||||||
|
var row=0;
|
||||||
|
var col=0;
|
||||||
|
var space=" ";
|
||||||
|
var port = {
|
||||||
|
// id: 'abc', // generated if `id` value is not present
|
||||||
|
group: 'a',
|
||||||
|
args: {}, // extra arguments for the port layout function, see `layout.Port` section
|
||||||
|
label: {
|
||||||
|
position: {
|
||||||
|
name: 'right',
|
||||||
|
args: { y: 6 } // extra arguments for the label layout function, see `layout.PortLabel` section
|
||||||
|
},
|
||||||
|
markup: '<text class="label-text" fill="blue"/>'
|
||||||
|
},
|
||||||
|
attrs: { text: { text: 'port1' } },
|
||||||
|
//markup: '<rect width="16" height="16" x="-8" strokegit ="red" fill="gray"/>'
|
||||||
|
};
|
||||||
|
|
||||||
|
var assetRects = [];
|
||||||
|
|
||||||
|
dataFile.assets.id.forEach(function(n) {
|
||||||
|
var rect = new joint.shapes.standard.Rectangle({
|
||||||
|
position: {x: (160*col+120), y: (240*row +120) },
|
||||||
|
size: {width: 120, height: 80},
|
||||||
|
ports: {
|
||||||
|
groups: {
|
||||||
|
'a': { position: 'top'},
|
||||||
|
'b': { position: 'bottom'}
|
||||||
|
},
|
||||||
|
items: [port]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
name = dataFile.assets.stencil[n-1].concat(space, dataFile.assets.testRole[n-1]);
|
||||||
|
//rect.position(240*row, 160*col);
|
||||||
|
//rect.resize(120, 80);
|
||||||
|
rect.attr({
|
||||||
|
body: {
|
||||||
|
fill: 'blue'
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
text: name,
|
||||||
|
fill: 'white'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assetRects.push(rect);
|
||||||
|
rect.addTo(graph);
|
||||||
|
col++;
|
||||||
|
if (col==5) {
|
||||||
|
col=0;
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var linkArray = [];
|
||||||
|
|
||||||
|
console.log(dataFile.logConns);
|
||||||
|
thisObj="Links ";
|
||||||
|
//Declare an array of links - assign names
|
||||||
|
dataFile.logConns.id.forEach(function(lc) {
|
||||||
|
//for (var id in dataFile.logConns) {
|
||||||
|
fromAsset = dataFile.logConns.fromId[lc-1];
|
||||||
|
toAsset= dataFile.logConns.toId[lc-1];
|
||||||
|
//console.log(thisObj.concat(lc, " ; ", fromAsset, " : ",toAsset, " : ", fromAsset, " ; ", assetRects[toAsset]));
|
||||||
|
var link = new joint.shapes.standard.Link();
|
||||||
|
link.source(assetRects[fromAsset-1]);
|
||||||
|
link.target(assetRects[toAsset-1]);
|
||||||
|
link.router('manhattan');
|
||||||
|
link.connector('jumpover');
|
||||||
|
linkArray.push(link);
|
||||||
|
link.addTo(graph);
|
||||||
|
});
|
||||||
|
|
||||||
|
paper.options.defaultRouter = {
|
||||||
|
name: 'manhattan',
|
||||||
|
args: {
|
||||||
|
elementPadding: 10
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
paper.on('cell:pointerclick', function(cellView) {
|
||||||
|
cellView.highlight();
|
||||||
|
console.log(cellView);
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Shiny.addCustomMessageHandler("render-laydown",
|
||||||
|
function(message){
|
||||||
|
try {
|
||||||
|
console.log("Draw diagram");
|
||||||
|
dataFile = message;
|
||||||
|
drawDiagram();
|
||||||
|
} catch(e) {
|
||||||
|
console.log("error object:");
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
$(document).on('shiny:inputchanged', function(event){
|
||||||
|
//TO BE INTEGRATED
|
||||||
|
});
|
||||||
61
www/js/getMouse.js
Normal file
61
www/js/getMouse.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* Retrieve the coordinates of the given event relative to the center
|
||||||
|
* of the widget.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* A mouse-related DOM event.
|
||||||
|
* @param reference
|
||||||
|
* A DOM element whose position we want to transform the mouse coordinates to.
|
||||||
|
* @return
|
||||||
|
* A hash containing keys 'x' and 'y'.
|
||||||
|
*/
|
||||||
|
function getRelativeCoordinates(event, reference) {
|
||||||
|
var x, y;
|
||||||
|
event = event || window.event;
|
||||||
|
var el = event.target || event.srcElement;
|
||||||
|
console.log(el);
|
||||||
|
if (!window.opera && typeof event.offsetX != 'undefined') {
|
||||||
|
// Use offset coordinates and find common offsetParent
|
||||||
|
var pos = { x: event.offsetX, y: event.offsetY };
|
||||||
|
|
||||||
|
// Send the coordinates upwards through the offsetParent chain.
|
||||||
|
var e = el;
|
||||||
|
while (e) {
|
||||||
|
e.mouseX = pos.x;
|
||||||
|
e.mouseY = pos.y;
|
||||||
|
pos.x += e.offsetLeft;
|
||||||
|
pos.y += e.offsetTop;
|
||||||
|
e = e.offsetParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for the coordinates starting from the reference element.
|
||||||
|
var ref = reference;
|
||||||
|
var offset = { x: 0, y: 0 };
|
||||||
|
while (ref) {
|
||||||
|
if (typeof ref.mouseX != 'undefined') {
|
||||||
|
x = ref.mouseX - offset.x;
|
||||||
|
y = ref.mouseY - offset.y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
offset.x += ref.offsetLeft;
|
||||||
|
offset.y += ref.offsetTop;
|
||||||
|
ref = ref.offsetParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset stored coordinates
|
||||||
|
ref = el;
|
||||||
|
while (ref) {
|
||||||
|
ref.mouseX = undefined;
|
||||||
|
reference.mouseY = undefined;
|
||||||
|
ref = ref.offsetParent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Use absolute coordinates
|
||||||
|
var pos = getAbsolutePosition(reference);
|
||||||
|
x = event.pageX - pos.x;
|
||||||
|
y = event.pageY - pos.y;
|
||||||
|
}
|
||||||
|
// Subtract distance to middle
|
||||||
|
return { x: x, y: y };
|
||||||
|
}
|
||||||
25919
www/js/joint.js
Normal file
25919
www/js/joint.js
Normal file
File diff suppressed because one or more lines are too long
13
www/js/jquery-ui.min.js
vendored
Normal file
13
www/js/jquery-ui.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
10220
www/js/jquery.js
vendored
Normal file
10220
www/js/jquery.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12352
www/js/lodash.js
Normal file
12352
www/js/lodash.js
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user