Skip to content
Permalink
main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
# See: https://github.rpi.edu/RensselaerIDEA/CohoesPVApp
library(usmap)
library(ggplot2)
library(plotly)
library(tidyverse)
library(RColorBrewer)
library(sf)
library(raster)
library(sp)
library(leaflet)
library(maps)
library(shiny)
library(htmltools)
library(rgdal)
library(maptools)
library(forcats)
library(DT)
# Set up the US map =====
# Read in the data of all reservoirs in the US and select relevant columns
reservoirs <- readRDS("data/general/reservoirs.Rds")
reservoirs_trim <- reservoirs %>%
dplyr::select("lat","lon"="long","dam_name", "pv_annual_kWh", "prim_owner")
# Convert prim_owner to factor of ownership types
transformed <- data.frame(
lon = reservoirs_trim$lon,
lat = reservoirs_trim$lat,
dam_name = reservoirs_trim$dam_name,
pv_annual_kWh = reservoirs_trim$pv_annual_kWh,
prim_owner = reservoirs_trim$prim_owner
)
transformed$prim_owner <-
factor(transformed$prim_owner,
levels = c("Federal","State","Local Government", "Public Utility","Private"))
# Line up lon and lat coordinates to those of the regular US map
transformed <- usmap_transform(transformed)
# Helper functions =====
# Load states data
# state_choices <- data.frame(state.name, state.abb)
# names(state_choices) <- c('State', 'Abbreviation')
# # Format state names
# state_choices$Adjusted_Name <- tolower(state_choices$State)
# state_choices$Adjusted_Name <- sub(' ', '_', state_choices$Adjusted_Name)
state_choices <- readRDS("data/general/state_choices.Rds")
# Linear regression model for determining zoom level
# Data
long_data <- c(0.972210, 0.100498, 3.206336, 3.723576, 0.410752, 7.002313, 0.628595, 0.111407,
1.972866, 2.147375, 0.486319, 5.967012, 5.397071, 0.102783, 0.196136, 12.009459,
8.152419)
lat_data <- c(0.700755, 0.094805, 2.108303, 3.164308, 0.142852, 4.011043, 14.279383, 0.126216,
2.289809, 1.053529, 0.573602, 3.588167, 4.195910, 0.086062, 0.179504, 4.643185,
4.056821)
ranges <- pmax(long_data,lat_data)
zoom_data <- c(8, 12, 8, 7, 12, 6, 5, 12, 8, 8, 10, 6, 7, 12, 11, 6, 5)
# Train the model
zoom_lm <- lm(zoom_data ~ ranges)
# Determine zoom level dynamically
zoomcalc <- function(myrange) {
return(round(predict(zoom_lm, data.frame(ranges = myrange))[[1]], 0))
}
# State dataset selection
get_dataset <- function(selected_state, which_type) {
# Get file name
state_name <- state_choices[which(state_choices$State == selected_state), 3]
file_name <- paste(state_name, '.Rds', sep = '')
# Generate the designated dataset
if (which_type == 'lowmod') {
return (readRDS(paste('data/lowmod/', file_name, sep = '')))
}
else if (which_type == 'cd') {
return (readRDS(paste('data/cong_districts/', file_name, sep = '')))
}
else if (which_type == 'reservoir') {
return (readRDS(paste('data/reservoirs/', file_name, sep = '')))
}
else if (which_type == 'substation') {
return (readRDS(paste('data/substations/', file_name, sep = '')))
}
return(NULL)
}
# Congressional district centering
get_view <- function(district) {
all_coords <- as.data.frame(st_coordinates(district))
long <- all_coords$X
lat <- all_coords$Y
long_range <- abs(abs(max(long)) - abs(min(long)))
lat_range <- abs(abs(max(lat)) - abs(min(lat)))
max_range <- max(long_range, lat_range)
long_avg <- mean(long)
lat_avg <- mean(lat)
zoom_level <- zoomcalc(max_range)
return(c(long_avg, lat_avg, zoom_level))
}
# Generalized function to create reactive data tables
# Type 1 - Rows = Primary owner type; Cols = Primary purpose
# Type 2 - Rows = Primary owner type; Cols = Low mod income buckets
# Type 3 - Rows = Primary purpose; Cols = Low mod income buckets
get_table <- function(reservoir_data, which_type) {
table_data <- NULL
if (which_type == 1) {
table_data <- table(reservoir_data$prim_owner, reservoir_data$prim_purpose)
} else if (which_type == 2) {
table_data <- table(reservoir_data$prim_owner, reservoir_data$lowmod_bucket)
} else if (which_type == 3) {
table_data <- table(reservoir_data$prim_purpose, reservoir_data$lowmod_bucket)
}
table_data <- as.data.frame.matrix(table_data)
if (which_type == 1) { # Sort rows and cols based on descending reservoir count
table_data <- table_data[order(-rowSums(table_data)), order(-colSums(table_data))]
}
table_data$Total = rowSums(table_data) # compute total for rows
table_data <- rbind(table_data, Total = colSums(table_data))
return(table_data)
}
# UI =====
ui <- fluidPage(
# Main website panel
titlePanel("Clean Energy Generation Capacity of Floating Solar on Reservoirs"),
navbarPage(
textOutput("input_text"),
id = "mainpage",
# State Estimated PV Production tab (homepage) =====
tabPanel(
"State Estimated PV Production",
value = "homepage",
# State and district selection
sidebarLayout(
sidebarPanel(
style = 'position: fixed',
width = 2,
selectInput(
inputId = 'state',
label = 'Choose a state:',
choices = state_choices$State,
selected = 'New York', # Make the default state NY
width = '150px'
),
selectInput(
inputId = 'district',
label = 'Highlight a district:',
choices = sort(unique(get_dataset('New York', 'lowmod')$DISTRICT)),
selected = '20' # Make the default district 20th (Cohoes)
),
# Range selection for substations
radioButtons(
inputId = 'distance',
label = 'Select the range (in miles) of displayed substations with respect to the center of the current district',
choices = list(10, 25, 50, 100),
width = '175px'
)
),
# Main panel for map and explanations
mainPanel(
width = 9,
style = 'position: relative',
# Map
tags$h3(textOutput('input_state')),
tags$h4("This map charts the NREL-identified water reservoirs potentially
'suitable' for floating solar in this state, by ownership and
potential electricity generation (per MWh)"),
tags$ul(
tags$li(
"Click on a dot to view reservoir name, estimated PV production and
census tract low/moderate income percentage."
),
tags$li(
"Click on an icon with lightning symbol to view information regarding an
electric substation."
),
tags$li(
"Select a congressional district (left) to highlight census tracts
in that district."
),
tags$li(
"NEW (Jan 2023): Congressional district boundaries for the ", tags$b("118th Congress")," are shown."
),
),
tags$br(),
leafletOutput('reservoir_map', height = '700'),
# Display statistics
tags$br(),
tags$p(
"**Income data used throughout this app is obtained from the US Census.
\"Low income\" is defined as up to 50 percent of
the Area Median Income (AMI); \"moderate income\" is
defined as greater than 50 percent AMI and up to 80 percent AMI.**"
),
tags$h3(textOutput('state_stats')),
tags$h4(textOutput('total_res')),
# Primary owner type / primary purpose data
tabPanel('Plot',
fluidRow(splitLayout(cellWidths = c('50%', '50%'),
plotOutput('owner_type_dist'),
plotOutput('prim_purpose_dist')))),
tags$br(),
tags$h4(textOutput('t1')),
tabPanel('Table', fluidRow(column(12, DT::dataTableOutput('table_1')))),
tags$br(),
# Low mod data
tags$h4("Distribution of low / moderate income levels across reservoir owner types and primary purposes"),
tabPanel('Plot',
fluidRow(splitLayout(cellWidths = c('50%', '50%'),
plotOutput('rc_owner_type'),
plotOutput('rc_prim_purpose')))),
tags$br(),
tags$h4(textOutput('t2')),
tabPanel('Table', fluidRow(column(12, DT::dataTableOutput('table_2')))),
tags$br(),
tags$h4(textOutput('t3')),
tabPanel('Table', fluidRow(column(12, DT::dataTableOutput('table_3')))),
# Explanation below map
tags$br(),
tags$h3('Further Information'),
tags$p(
"The sources of data are listed under the \"Data Sources of the Floating Solar Explorer\"
section of the \"About the Floating Solar Explorer\" page"
),
tags$p(
"Developed by the Rensselaer Institute for Data Exploration
and Applications (IDEA) in support of the proposed City of Cohoes, NY
Municipal Floating Solar Demonstration Project"
),
tags$p(
"For more information on the Cohoes, NY Municipal Floating Solar
Demonstration project contact: Theresa Bourgeois, Director of
Operations, City of Cohoes",
tags$a(
"TBourgeois@ci.cohoes.ny.us", href="mailto:TBourgeois@ci.cohoes.ny.us"
),
"or 518-903-0142 or Joseph Seman-Graves, City Planner, City of Cohoes",
tags$a(
"JSeman-Graves@ci.cohoes.ny.us", href="mailto:JSeman-Graves@ci.cohoes.ny.us"
),
"or 518-233-2130"
),
# IDEA logo
img(src='IDEA_logo_500.png', align = "right", height=75)
)
)
),
# US Estimated PV Production tab (overview of all reservoirs) =====
tabPanel(
"US Estimated PV Production",
value ="us_page",
# Explanation above map
fluidRow(
style = "height:100px;",
column(
width=12,
tags$h3(
"Floating Solar installed on 'suitable' water reservoirs in the U.S.
could generate about 10% of the nation’s current annual electricity
production, according to a 2018 National Renewable Energy Lab (NREL) study"
),
tags$p(
"This map charts the 24,419 NREL-identified water reservoirs
potentially 'suitable' for floating solar, by ownership and potential
electricity generation (per MWh)"
)
)
),
# Continue explanation above map and plot the US map
# TODO: Improve the map's interactability
fluidRow(
style = "height:850px;",
column(
width=12,
tags$p(
tags$i(
"Zoom in on a region by clicking, dragging and releasing",
tags$br(),
"Reset by selecting 'autoscale' option
(hover over upper right of map to see menu)"
)
),
tags$div(
style="float:left;",
plotlyOutput("us_map")
)
)
),
#Explanation below map
fluidRow(
style = "height:200px;",
column(
width=12,
tags$p(
"Estimated photovoltaic production data provided by National
Renewable Energy Laboratory (NREL); see:",
tags$a(
"Floating photovoltaic systems: assessing the technical potential of
photovoltaic systems on man-made water bodies in the continental
United States.", href="https://pubs.acs.org/doi/abs/10.1021/acs.est.8b04735"
),
"Regarding 'suitability,' the NREL study notes:",
tags$i(
"the high-level data used and analyzed lacks the resolution for
case-by-case feasibility, and the results should only be considered
as a starting point for national and regional examinations."
)
),
tags$p(
"Estimated reservoir area obtained from US Army Corps of Engineers
(USACE). The NREL model and the underlying data may contain errors."
),
tags$p(
"Income data obtained from the US Census.
Low income is defined as up to 50 percent of
the Area Median Income (AMI); moderate income is
defined as greater than 50 percent AMI and up to 80 percent AMI."
),
tags$p(
"Developed by the Rensselaer Institute for Data Exploration
and Applications (IDEA) in support of the proposed City of Cohoes,
NY Municipal Floating Solar Demonstration Project."
),
tags$p(
"For more information on the Cohoes, NY Municipal Floating Solar
Demonstration project contact: Theresa Bourgeois, Director of
Operations, City of Cohoes",
tags$a(
"TBourgeois@ci.cohoes.ny.us", href='mailto:TBourgeois@ci.cohoes.ny.us'
),
'or 518-903-0142 or Joseph Seman-Graves, City Planner, City of Cohoes',
tags$a(
'JSeman-Graves@ci.cohoes.ny.us',href='mailto:JSeman-Graves@ci.cohoes.ny.us'
),
'or 518-233-2130'
),
# IDEA logo
img(src='IDEA_logo_500.png', align = "right", height=75)
)
)
),
# Background information tab =====
tabPanel(
'About the Floating Solar Explorer', value = 'about',
# Picture and paragraph on the right
tabPanel('',
fluidRow(
column(5,
tags$h1(img(src='20190731-nrel-fpv-install-53282.jpg', align = "center", height=250)),
tags$p('FPV Installation in Walden, Colorado',
tags$i('Photo by Dennis Schoreder via'),
tags$a('NREL', href = 'http://bit.ly/3cyhq2A'))
),
column(7,
tags$h5('Floating Solar installed on suitable water reservoirs in the U.S.
could generate about 10% of the nation’s current annual electricity
production, according to a 2018 National Renewable Energy Lab (NREL)
study'),
tags$p("Floating Solar installed on the 24,419 suitable human-made water
reservoirs in the United States could generate about 10% of the nation’s
current annual electricity production, according to a 2018 National
Renewable Energy Lab (NREL) study. The 2018 NREL report indicates there
are 492 reservoirs in New York State alone, encompassing 134,425 acres of
water suitable for Floatovoltaics. This could generate 16.4 TW-hr/yr."),
tags$p("The City of Cohoes, New York is proposing a",
tags$i("municipally owned and operated"),
"(apparently first of its kind) 3.2 MWdc Floating Solar demonstration project
to be installed on its water reservoir, at a cost of $5.9 million. The Cohoes
clean energy project would demonstrate that leveling the playing field by
providing grants to municipalities — as an alternative option to current
tax credits for private investments — for Floating Solar installations would
incentivize municipalities to invest in their own clean energy infrastructure
in a sustainable way, while realizing the full economic benefits of
doing so. The Cohoes project may also spark interest in tapping appropriate
water surfaces as a viable platform for solar energy generation, and would
offer K-to-College opportunities for STEM education, workforce development,
and research.")
)
)
),
# Quote
tags$br(),
tags$p(tags$b(
'Words of support from U.S. Rep. Paul Tonko (D-NY20), Chair of the U.S.
House Energy and Commerce Committee’s Subcommittee on Environment and
Climate Change, in an April 2021 announcement of his request for Federal
funding to implement the Cohoes, NY Municipal Floating Solar
Demonstration Project:')),
tags$p(tags$blockquote(tags$i(
'“The Cohoes floating solar initiative offers a groundbreaking opportunity
to localize power generation, increase grid stability and drive down
utility costs for consumers. I applaud this bold collaboration to develop
innovative solutions that will help us realize the full potential of our
energy infrastructure, and I hope this project can serve as a model for
tackling some of America’s thorniest challenges regarding clean energy
generation and preventing the worst outcomes of the climate crisis.”
U.S. Rep Paul Tonko said.'))),
# More info
tags$p(
'This "Floating Solar Explorer" has been developed by the Rensselaer
Institute for Data Exploration and Applications (IDEA) at Rensselaer
Polytechnic Instuitute in support of the proposed City of Cohoes, NY
Municipal Floating Solar Demonstration Project. This initial collaboration
is designed to visualize the energy-generation opportunities and potential
economic impact of adopting floating solar on human-made water reservoirs. '
),
tags$p(
"The Floating Solar Explorer’s U.S. map charts the 24,419 NREL-identified
water reservoirs potentially 'suitable' for floating solar, by ownership
and potential electricity generation (per MWh)."
),
tags$p(
'The individual state map charts the NREL-identified water reservoirs
potentially "suitable" for floating solar in the selected state, by ownership
and potential electricity generation (per MWh).'
),
tags$p(
'A municipally owned and operated floating solar installation not only
generates clean energy, it has the capacity to generate economic opportunity
for the community as a result of electric bill savings. The City of Cohoes,
a Low/Moderate Income (LMI) community with an Environmental Justice
(EJ) designation, anticipates saving approximately $500,000 per year
in electricity costs; money that can be reinvested back into the working
class community.'
),
tags$p(
'The Floating Solar Explorer incorporates economic data, to better
illustrate where the state and national potential is for municipal
floating solar installations in LMI communities like Cohoes.'
),
tags$p(
'Meeting the ambitious and essential clean energy goals that have been
set at the Federal, State, and local levels will require all sectors at
all levels to do their part. Cities are on the front lines of that effort,
and must lead by example to create the necessary changes at the required
pace. Municipally owned and operated floating solar installations may
offer a new opportunity to generate success.'
),
tags$p(
'This early-stage Rensselaer IDEA project, developed by students and staff,
is an example of the type of Floating Solar-related undergraduate student
engagement and university-based research projects that can be sparked by
and/or help advance this clean energy technology’s growth in the U.S.'
),
# Data Sources block
tags$h3("Data Sources of the Floating Solar Explorer"),
tags$p("Estimated photovoltaic production data provided by National Renewable
Energy Laboratory (NREL); see:",
tags$a("Floating photovoltaic systems: assessing the technical potential
of photovoltaic systems on man-made water bodies in the continental
United States.",
href="https://pubs.acs.org/doi/abs/10.1021/acs.est.8b04735"),
"Regarding 'suitability,' the NREL study notes:",
tags$i("the high-level data used and analyzed lacks the resolution for
case-by-case feasibility, and the results should only be considered
as a starting point for national and regional examinations.")),
tags$p("Estimated reservoir area obtained from US Army Corps of Engineers
(USACE). The NREL model and the underlying data may contain errors."),
tags$p("Income data on the State Map is obtained from the US Census. Low income
is defined as up to 50 percent of the Area Median Income (AMI); moderate
income is defined as greater than 50 percent AMI and up to 80 percent AMI."),
tags$p("Electric substation data on the State Map is obtained from the Homeland
Infrastructure Foundation-Level Data (HIFLD)."),
# Further information block
tags$h3('Further information'),
tags$p("Developed by the Rensselaer Institute for Data Exploration and Applications
(IDEA) in support of the proposed City of Cohoes, NY Municipal Floating Solar
Demonstration Project"),
tags$p('NREL:',
tags$a('NREL Details Great Potential for Floating PV Systems; Technology
Already in Widespread Use Overseas, Especially in Japan.',
href='https://www.nrel.gov/news/press/2018/nrel-details-great-potential-for-floating-pv-systems.html'),
'News release (Dec. 27, 2018)'),
tags$p('About The Rensselaer IDEA:',
tags$a('https://idea.rpi.edu/', href='https://idea.rpi.edu/')),
tags$p('Building Floating Solar in Cohoes:',
tags$a('https://www.ci.cohoes.ny.us/523/Building-Floating-Solar-in-Cohoes',
href='https://www.ci.cohoes.ny.us/523/Building-Floating-Solar-in-Cohoes')),
tags$p('For more information on the Cohoes, NY Municipal Floating Solar Demonstration
project contact: Theresa Bourgeois, Director of Operations, City of Cohoes',
tags$a('TBourgeois@ci.cohoes.ny.us',href='mailto:TBourgeois@ci.cohoes.ny.us'),
'or 518-903-0142 or Joseph Seman-Graves, City Planner, City of Cohoes',
tags$a('JSeman-Graves@ci.cohoes.ny.us', href='mailto:JSeman-Graves@ci.cohoes.ny.us'),
'or 518-233-2130'),
# IDEA logo
img(src='IDEA_logo_500.png', align = "right", height=75)
)
)
)
# Server =====
server <- function(input, output, session) {
# Data =====
lowmod_data <- reactive({return(get_dataset(input$state, 'lowmod'))})
cd_data <- reactive({return(get_dataset(input$state, 'cd'))})
reservoir_data <- reactive({return(get_dataset(input$state, 'reservoir'))})
substation_data <- reactive({return(get_dataset(input$state, 'substation'))})
# Electric substation icon =====
sub_icon <- makeIcon(
iconUrl = 'substation.png',
iconWidth = 18,
iconHeight = 18
)
# Update congressional district selection upon changing states =====
# Set to At-large for states containing only one congressional district
# Default to 20 for New York
# Set to 1 for other states
get_sel_dist <- reactive({
single_dist_states <- c('Alaska', 'Delaware', 'Montana', 'North Dakota',
'South Dakota', 'Vermont', 'Wyoming')
if (input$state %in% single_dist_states) {
return('At-large')
} else if (input$state == 'New York') {
return('20')
} else {
return('1')
}
})
observeEvent(
input$state, {
updateSelectInput(session,
inputId = 'district',
choices = sort(unique(lowmod_data()$DISTRICT)),
selected = get_sel_dist())
}
)
# Reactive outputs, excluding state reservoirs map ====
# Show currently selected state on the top left corner
output$input_text <- renderText(paste0('Selected State: ',
state_choices[which(state_choices$State == input$state), 2]))
# Show currently selected state above map
output$input_state <- renderText(paste('Potentially Suitable Reservoirs in ', ' by Census Tract',
sep = input$state))
# State statistics
output$state_stats <- renderText(paste('State Statistics of ', input$state, sep = ''))
output$total_res <- renderText(paste0('Total number of potentially suitable reservoirs
for floating solar: ',
nrow(reservoir_data()), sep = ''))
output$owner_type_dist <- renderPlot(ggplot(data = reservoir_data(),
aes(x = fct_infreq(prim_owner),
fill = prim_purpose)) +
geom_bar(position = 'stack') +
ggtitle('Distribution of Primary Purposes Across Reservoir Owner Types') +
xlab('Reservoir Owner Type') + ylab('Count') +
theme(text = element_text(size = 10)) +
scale_fill_discrete(name = "Primary Purpose"))
output$prim_purpose_dist <- renderPlot(ggplot(data = reservoir_data(),
aes(x = fct_infreq(prim_purpose),
fill = prim_owner)) +
geom_bar(position = 'stack') +
ggtitle('Distribution of Reservoir Owner Types Across Primary Purposes') +
xlab('Primary Purpose') + ylab('') +
theme(text = element_text(size = 10)) +
scale_fill_manual(
name = "Reservoir Owner Type",
values = c(
'Federal' = '#7FC97F',
'State' = '#BEAED4',
'Local Government' = '#FDC086',
'Public Utility' = '#FFFF99',
'Private' = '#386CB0'
)))
output$rc_owner_type <- renderPlot(ggplot(data = reservoir_data(),
aes(x = fct_infreq(prim_owner),
fill = lowmod_bucket)) +
geom_bar(position = 'stack') +
xlab('Reservoir Owner Type') + ylab('Count') +
theme(text = element_text(size = 10)) +
scale_fill_manual(
name = "Low/Mod Income Level",
values = c(
'0 - 20' = '#f7f7f7',
'20 - 40' = '#cccccc',
'40 - 60' = '#969696',
'60 - 80' = '#636363',
'80 - 100' = '#252525',
'No LMI Data' = '276DC2'
)))
# + theme(legend.position = 'none'))
output$rc_prim_purpose <- renderPlot(ggplot(data = reservoir_data(),
aes(x = fct_infreq(prim_purpose),
fill = lowmod_bucket)) +
geom_bar(position = 'stack') +
xlab('Primary Purpose') + ylab('') +
theme(text = element_text(size = 10)) +
scale_fill_manual(
name = "Low/Mod Income Level",
values = c(
'0 - 20' = '#f7f7f7',
'20 - 40' = '#cccccc',
'40 - 60' = '#969696',
'60 - 80' = '#636363',
'80 - 100' = '#252525',
'No LMI Data' = '276DC2'
)))
output$table_1 <- renderDataTable(get_table(reservoir_data(), 1),
options = list(dom = 't'))
output$table_2 <- renderDataTable(get_table(reservoir_data(), 2),
options = list(dom = 't'))
output$table_3 <- renderDataTable(get_table(reservoir_data(), 3),
options = list(dom = 't'))
output$t1 <- renderText(paste('Breakdown of reservoir types in ', input$state, sep = ''))
output$t2 <- renderText(paste('Reservoir distribution in ',
', categorized by reservoir owner types, across low / moderate income levels',
sep = input$state))
output$t3 <- renderText(paste('Reservoir distribution in ',
', categorized by primary purposes, across low / moderate income levels',
sep = input$state))
# State reservoirs map =====
# Shading for census tracts =====
bins <- c(0, 20, 40, 60, 80, 100)
dam_colors <- brewer.pal(n = 5, name = 'Accent')
dam_labels <- c("Federal",
"State",
"Local Government",
"Public Utility",
"Private")
names(dam_colors) <- dam_labels
pal_dam <- colorFactor(dam_colors,
levels = as.factor(dam_labels),
ordered = TRUE)
tag.map.title <- tags$style(HTML("
.leaflet-control.map-title {
transform: translate(-50%,20%);
position: fixed !important;
left: 50%;
text-align: left;
padding-left: 10px;
padding-right: 10px;
background: rgba(255,255,255,0.75);
font-weight: bold;
font-size: 20px;
}"))
# Congressional district selection for leaflet =====
current_district <- reactive({
d <- input$district
temp <- lowmod_data() %>% filter(DISTRICT == input$district)
if (length(st_coordinates(temp)) == 0) {
if (length(unique(lowmod_data()$DISTRICT)) == 1) { # Single congressional district states
d <- 'At-large'
} else { # States with multiple congressional districts
d <- 1
}
temp <- lowmod_data() %>% filter(DISTRICT == d)
}
return(temp)
})
# Palette =====
dist_pal <- reactive({
colorBin(palette = 'Greys', domain = current_district()$Lowmod_pct, bins = bins)
})
# Get dynamic zoom info =====
district_view <- reactive({
get_view(current_district())
})
# Substation selection =====
substations_in_range <- reactive({
view <- get_view(current_district())
# Get the center longitude and latitude of the currently selected district
center_long <- view[1]
center_lat <- view[2]
# Filter substations to those within the selected range
# One degree of latitude = 69 miles; one degree of longitude = 54.6 miles
subs_in_range <- substation_data() %>%
filter(sqrt(((LATITUDE - center_lat) * 69) ^ 2 + ((LONGITUDE - center_long) * 54.6) ^ 2)
<= as.integer(input$distance))
return(subs_in_range)
})
# Leaflet map =====
output$reservoir_map <- renderLeaflet({
leaflet() %>%
# Background map
addTiles() %>%
# Dynamic zoom
setView(lng = district_view()[1],
lat = district_view()[2],
zoom = district_view()[3]) %>%
# Reservoir coloring legend ('Reservoir Owner Type')
addLegend("topleft",
colors = c("#7FC97F","#BEAED4","#FDC086","#FFFF99","#386CB0"),
labels = dam_labels,
title = "Reservoir Owner Type",
opacity = 1 ,
labFormat = function(type, cuts, p){ # Forces correct label order
paste0(dam_labels)
}) %>%
# Census tract legend ('Percentage Low or Moderate Income')
addLegend('topleft',
pal = dist_pal(),
values = current_district()$Lowmod_pct,
title = 'Percentage of Low or </br>Moderate Income',
opacity = 1)
})
# Update congressional district shading, outline, and markers upon
# changing districts, state, or substation range
observeEvent(c(input$state, input$district, input$distance), {
leafletProxy('reservoir_map', session) %>%
# Clear substations and range circle upon update
clearGroup(group = list('substations', 'range', 'census_tract')) %>%
# Census tract shading within the selected congressional district
addPolygons(
data = current_district(),
fillColor = ~dist_pal()(Lowmod_pct), # color of census tract shading
color = 'black', # color of census tract borders
fillOpacity = 0.7, # opacity of shading
weight = 0.75, # width of census tract border
group = 'census_tract'
) %>%
# Substation range circle
addCircles(
lng = district_view()[1],
lat = district_view()[2],
weight = 1,
radius = as.integer(input$distance) * 1609.34, # leaflet radius is in meters
color = 'blue',
fillColor = 'lightblue',
fillOpacity = 0,
group = 'range'
) %>%
# Congressional district outline
addPolygons(
data = cd_data(),
weight = 2,
fillOpacity = 0,
color = 'green',
group = 'outline'
) %>%
# Reservoirs
addCircleMarkers(
data= reservoir_data(),
weight = 2,
opacity = 1,
radius = 5,
fillOpacity = 1,
lng=reservoir_data()$long,
lat=reservoir_data()$lat,
color=~pal_dam(as.factor(reservoir_data()$prim_owner)),
group = 'reservoirs',
popup = paste0(
reservoir_data()$dam_name,"<br/>",
"Primary Purpose: ", reservoir_data()$prim_purpose, "<br/>",
"Reservoir Owner Type: ", reservoir_data()$prim_owner, "<br/>",
"Low/Mod Income Pct: ", reservoir_data()$Lowmod_pct,"%<br/>",
"Estimated Surface Area (USACE): ",reservoir_data()$nid_area," acres<br/>",
"Estimated PV Annual Production (NREL): ",reservoir_data()$pv_annual_kWh/1000," MWh<br/>",
NULL
)
) %>%
# Substations
addMarkers(
data = substations_in_range(),
lng=substations_in_range()$LONGITUDE,
lat=substations_in_range()$LATITUDE,
icon = sub_icon,
group = 'substations',
popup = paste0(substations_in_range()$NAME, '<br/>',
'Substation ID: ', substations_in_range()$ID, "<br/>",
'Location: ', str_to_title(substations_in_range()$CITY),
', ', substations_in_range()$STATE, '<br/>',
'Type: ', str_to_title(substations_in_range()$TYPE), '<br/>',
'Status: ', str_to_title(substations_in_range()$STATUS), '<br/>',
'Source: eia.gov<br/>',
NULL
)
)
})
# Plot the US map =====
output$us_map <- renderPlotly({
p1 <- plot_usmap() +
geom_point(data = transformed,
aes(x = x, y = y,
size=pv_annual_kWh,
text = dam_name,
color = prim_owner)) +
labs(title = "Estimated Photovoltaic Production of US Reservoirs",
subtitle = "Source: NREL") +
theme(legend.position = "right") +
scale_colour_manual(name = "Owner Type", values = dam_colors)
p2 <- ggplotly(p1, tooltip = c("dam_name","prim_owner"))
m <- list(
l = 50,
r = 50,
b = 100,
t = 100,
pad = 4
)
p2 %>% layout(autosize = F,
width = 1000, height = 900, margin = m,
legend = list(
orientation = "h"
))
})
# Content of modal dialog
query_modal <- modalDialog(
title = "Welcome to the Floating Solar Explorer",
"PLEASE NOTE: This application is the result of the efforts of students
and staff of the Rensselaer IDEA in collaboration with the City of Cohoes, NY.
This is a prototype application and may not meet all of the standards one might
expect of a production commercial product.",
easyClose = F,
footer = tagList(actionButton("run", "Continue with the Floating Solar Explorer"))
)
# Creates modal dialog
showModal(query_modal)
# Removes modal
observeEvent(input$run, {removeModal()})
}
shinyApp(ui, server)