class: center, middle, inverse, title-slide .title[ # Volcano App - Developing Data Products Course Project ] .author[ ### Pedro Medeiros ] .date[ ### 2025-01-08 ] --- ## Introduction This presentation is the Course Project of the Developing Data Products Coursera course. It is an R Presentation generated with RStudio. The Shiny application is available at http://pm-amora.shinyapps.io/Data_Products The Shiny app source code is available at https://github.com/pm-amora/DDP ## Overview > The application is written in Shiny, a web application framework for R. > The source code consists of two files: server.R and ui.R. > server.R includes the backend of a Shiny web application. > ui.R includes the the user-interface elements. > The application is hosted on Rstudio's shiny server. The application goal is to provide a 3d surface interface to explore the Volcano dataset. The volcano and rainfall dataset are a built-in R dataset that contains a matrix of topographic data combined with the amount of rainfall. --- ## How the App works? ### Side Panel The sidebar panel contains interactive input controls, such as sliders, dropdowns, checkboxes, or text inputs. These inputs allow users to specify parameters or settings for the Volcano topography and its amount of rainfall. > Purpose: Collect user preferences and send them to the server. > Interaction: The user changes a value in order to see the different perspectives of the volcano and how the rainfall changes according to its topography. ### Main Panel The main panel displays the outputs (e.g., plots, tables, text) that are generated based on the user's input. > Purpose: Render and display the result of the user's interaction with the app. > Output: Contents are dynamically updated, in this case the Volcano plot along with the amount of rainfall. --- ## UI Code ``` r # Load required Libraries library(shiny) library(plotly) library(viridis) # Define UI ui <- fluidPage( titlePanel("Volcano and Rainfall Visualization"), sidebarLayout( sidebarPanel( sliderInput("rainScale", "Rainfall Scale:", min = 0, max = 2, value = 1, step = 0.1), sliderInput("zoom", "Zoom Level (Z-Axis):", min = 0.5, max = 3, value = 1, step = 0.1), sliderInput("rainMin", "Rainfall Minimum:", min = 0, max = 200, value = 0) , sliderInput("rainMax", "Rainfall Maximum:", min = 0, max = 200, value = 200), sliderInput("opacity", "Surface Opacity:", min = 0.1, max = 1, value = 1, step = 0.1), selectInput("colorPalette", "Color Palette:", choices = c("viridis", "heat.colors", "terrain.colors", "topo.colors")), checkboxInput("showRain", "Overlay Rainfall", value = TRUE), checkboxInput("showGrid", "Show Grid Lines", value = TRUE) ), mainPanel( plotlyOutput("combinedPlot") ) ) ) ``` --- ## Server Code ``` r # Generate synthetic rainfall data set.seed(123) # Ensure reproducibility rainfall <- matrix(runif(length(volcano), min = 0, max = 200), nrow = nrow(volcano), ncol = ncol(volcano)) # Define Server server <- function(input, output) { output$combinedPlot <- renderPlotly({ # Base elevation from volcano dataset z_base <- volcano # Apply rainfall if selected rainfall_clipped <- pmin(pmax(rainfall, input$rainMin), input$rainMax) Amount_rain <- if (input$showRain) { z_base + (rainfall_clipped * input$rainScale) } else { z_base } # Generate x and y coordinates x <- seq_len(nrow(z_base)) y <- seq_len(ncol(z_base)) # Define color palette palette <- switch( input$colorPalette, "heat.colors" = heat.colors(100), "terrain.colors" = terrain.colors(100), "topo.colors" = topo.colors(100), "viridis" = viridis::viridis(100) # Viridis is already Plotly-compatible ) # Convert the palette into Plotly-compatible colorscale colorscale <- lapply(seq_along(palette), function(i) { list((i - 1) / (length(palette) - 1), palette[i]) }) # Create 3D surface plot plot_ly( z = ~Amount_rain, x = ~x, y = ~y, type = "surface", colorscale = colorscale, opacity = input$opacity ) %>% layout(scene = list( camera = list( eye = list(x = 1.5, y = 1.5, z = input$zoom) ), xaxis = list(visible = input$showGrid), yaxis = list(visible = input$showGrid), zaxis = list(title = if (input$showRain) "Elevation + Rainfall" else "Elevation") )) }) } ```