Skip to content

Commit d4ea1c6

Browse files
authored
Merge pull request #150 from terraref/feature
First draft of Shiny app
2 parents e535a07 + 793ad29 commit d4ea1c6

4 files changed

Lines changed: 163 additions & 88 deletions

File tree

experiment-trait-data-visualizer/.gitignore

Lines changed: 0 additions & 2 deletions
This file was deleted.

experiment-trait-data-visualizer/api_data_helpers.py

Lines changed: 0 additions & 57 deletions
This file was deleted.
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
library(shiny)
2+
library(traits)
3+
library(ggplot2)
4+
library(lubridate)
5+
library(DataCache)
6+
library(timevis)
7+
8+
# set options for BETYdb API
9+
knitr::opts_chunk$set(echo = FALSE, cache = TRUE)
10+
options(betydb_key = readLines('~/.betykey', warn = FALSE),
11+
betydb_url = "https://terraref.ncsa.illinois.edu/bety/",
12+
betydb_api_version = 'beta')
13+
14+
# get list of seasons for user to select from
15+
experiments <- as.data.frame(betydb_query(table='experiments'))
16+
seasons <- unique(experiments[c('start_date', 'end_date')])
17+
rownames(seasons) <- paste0('[', seasons$start_date, ']', ' - ', '[', seasons$end_date, ']')
18+
19+
# set page UI
20+
ui <- fluidPage(
21+
22+
column(width=8, offset=2,
23+
title = "TERRA-REF Experimental Data",
24+
25+
h1('TERRA-REF Experimental Data'),
26+
27+
# season menu
28+
selectInput('selectedSeason', 'Season', rownames(seasons)),
29+
30+
hr(),
31+
32+
h3('Trait Data'),
33+
34+
# variable menu to be rendered when variables for a given season are parsed in server()
35+
uiOutput('selectVariable'),
36+
37+
plotOutput('traitPlot'),
38+
39+
hr(),
40+
h3('Managements Data'),
41+
42+
timevisOutput('timeline')
43+
)
44+
45+
)
46+
47+
# load trait data from BETYdb
48+
# function is used only by DataCache library to get and update data
49+
loadTraitData <- function(startDate, endDate) {
50+
51+
# set progress bar while API is queried
52+
withProgress(message="Retrieving BETYdb Data", value=0, {
53+
54+
fullTraitData <- data.frame()
55+
56+
initialDateDiff <- as.numeric(difftime(endDate, startDate, units="days"))
57+
currDate <- startDate
58+
# loop through all days in a given season
59+
while (endDate - currDate != 0) {
60+
# get trait data for each day
61+
currTraitData <- betydb_query(table='traits', date=paste0('~', currDate), limit='none')
62+
fullTraitData <- rbind(fullTraitData, currTraitData[c('date', 'mean', 'variable_id', 'specie_id')])
63+
currDate <- currDate + days(1)
64+
65+
# update progress bar
66+
incProgress(1/initialDateDiff)
67+
}
68+
})
69+
70+
# format data as for usability with DataCache library
71+
retData <- list(fullTraitData)
72+
names(retData) <- 'fullTraitData'
73+
74+
return(retData)
75+
}
76+
77+
getManagementsData <- function(startDate, endDate) {
78+
79+
fullMgmtData <- data.frame()
80+
81+
currDate <- startDate
82+
while (endDate - currDate != 0) {
83+
# get management data for each day
84+
currMgmtData <- betydb_query(table='managements', date=paste0('~', currDate))
85+
fullMgmtData <- rbind(fullMgmtData, currMgmtData[c('date', 'mgmttype')])
86+
currDate <- currDate + days(1)
87+
}
88+
89+
return(fullMgmtData)
90+
}
91+
92+
# handle all app logic
93+
server <- function(input, output) {
94+
95+
# set reactive start date and end date variables to change when selected season changes
96+
selectedSeasonRow <- reactive({ seasons[input$selectedSeason,] })
97+
seasonStartDate <- reactive({ as.Date(selectedSeasonRow()$start_date) })
98+
seasonEndDate <- reactive({ as.Date(selectedSeasonRow()$end_date) })
99+
100+
# set unique cache name for date range for usability with DataCache library
101+
cacheName <- reactive({ paste0('TraitCache_', seasonStartDate(), '_', seasonEndDate()) })
102+
103+
# render menu for selecting variable to view data for
104+
output$selectVariable <- renderUI({
105+
106+
# get access to 'fullTraitData' from cache
107+
data.cache(cache.name=cacheName(), loadTraitData, startDate=seasonStartDate(), endDate=seasonEndDate(), frequency='daily')
108+
109+
# get unique variable ids from observations in current season
110+
variableIds <- unique(as.numeric(fullTraitData$variable_id))
111+
112+
# query API for readable names for variable ids, set names
113+
variableNames <- vector()
114+
for (variableId in variableIds) {
115+
varName <- betydb_query(table='variables', id=variableId)$name
116+
varName <- gsub('_', ' ', varName)
117+
variableNames <- c(variableNames, varName)
118+
}
119+
names(variableIds) <- variableNames
120+
121+
selectInput('selectedVariable', 'Variable', variableIds)
122+
})
123+
124+
# render plot for selected variable
125+
output$traitPlot <- renderPlot({
126+
127+
# get access to 'fullTraitData' from cache
128+
data.cache(cache.name=cacheName(), loadTraitData, startDate=seasonStartDate(), endDate=seasonEndDate())
129+
130+
# only render plot of a variable is selected
131+
if (!is.null(input$selectedVariable)) {
132+
# get observations for selected variable
133+
variableIdData <- betydb_query(table='variables', id=input$selectedVariable)
134+
variableTraitData <- subset(fullTraitData, variable_id==as.numeric(variableIdData$id))
135+
136+
# get specie data for title
137+
specieId <- unique(as.numeric(variableTraitData$specie_id))
138+
specieData <- betydb_query(table='species', id=specieId)
139+
title <- paste0('Mean ', gsub('_', ' ', variableIdData$name), ' for ', specieData$scientificname)
140+
141+
# generate timeseries of boxplots from mean value
142+
ggplot(variableTraitData, aes(as.Date(date), mean)) +
143+
geom_boxplot(aes(group=cut_width(as.Date(date), 1))) +
144+
labs(title=title,
145+
x="Observation Dates", y=variableIdData$units) +
146+
theme(text = element_text(size=20), axis.text.x = element_text(angle=45, hjust=1)) +
147+
expand_limits(y=0) + xlim(seasonStartDate(), seasonEndDate())
148+
}
149+
})
150+
151+
# generate timeline visualization for managements data
152+
output$timeline <- renderTimevis({
153+
mgmtData <- getManagementsData(startDate=seasonStartDate(), endDate=seasonEndDate())
154+
timelineData <- data.frame(
155+
id=1:nrow(mgmtData),
156+
content=paste0(mgmtData$mgmttype),
157+
start=as.Date(mgmtData$date)
158+
)
159+
timevis(timelineData)
160+
})
161+
}
162+
163+
shinyApp(ui=ui, server=server)

experiment-trait-data-visualizer/trait_data_retrieval.py

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)