R/tagCell_server.R

Defines functions tagCellServer

Documented in tagCellServer

#' Shiny app server function for tagCell
#' Define server logic required to draw a histogram
#' @param input provided by shiny
#' @param output provided by shiny
#' @param session provided by shiny
#' @import shiny shinyjs formattable dplyr tidyr hexbin magick
#' @importFrom graphics polygon
tagCellServer <- function(input, output, session) {
  print("tagCellServer 1: start")
  d <- cdata %>% 
    dplyr::arrange(ucid, t.frame) %>% 
    {if(randomize_ucids) 
      sample(x = split(., .$ucid), 
             size = length(unique(cdata$ucid))) %>% 
        bind_rows() else .} %>% 
    mutate(ucid_t.frame = paste(ucid, t.frame, sep = "_")) %>% 
    mutate(
      cellID = as.integer(cellID),
      ucid = as.integer(ucid),
      t.frame = as.integer(t.frame)
    )
  p <- paths
  
  ucid.unique <- unique(d$ucid)
  if(!all.unique(d$ucid_t.frame)) stop("tagCellServer error: the ucid-t.frame combination is not a primary key! check your data.")
  
  reactive_values <- shiny::reactiveValues(ith_cell = 1, # row index used to order dataframe rows
                                           ith_ucid = numeric(),
                                           i_line = 1,
                                           other_reactive_values = c(),
                                           selected_cell_tags = list(),
                                           click_vars = list())
  
  ### UI OBSERVERS   ----------------
  output$moreControls <- renderUI({
    # tagList(
      # sliderInput("n", "N", 1, 1000, 500),
      # textInput("label", "Label")
    # )
    # shiny::selectInput('tags','Tag', cell_tags, multiple = TRUE, selected = NULL, selectize = T)
    # ith_cell <- reactive_values$ith_cell
    # selected_cell_tags <- reactive_values$selected_cell_tags
    # 
    # print("- Generating seelctInput fields...")
    # print(ith_cell)
    # print(selected_cell_tags[ith_cell])
    print("tagCellServer 2: renderUI update")
    lapply(1:length(names(cell_tags)), function(tag_group){
      # shiny::selectInput(inputId = names(cell_tags)[tag_group], 
      #                    label = names(cell_tags)[tag_group],
      #                    choices = cell_tags[tag_group],
      #                    multiple = TRUE,
      #                    # selected = unlist(selected_cell_tags[ith_cell])[tag_group],
      #                    selected = NULL,
      #                    selectize = T)
      shiny::checkboxGroupInput(inputId = names(cell_tags)[tag_group], 
                                label = names(cell_tags)[tag_group],
                                choices = unlist(cell_tags[tag_group])
                                # choices = list("asd", "dddd")
                                )
    })
  })
  
  ### INPUT OBSERVERS   ----------------
  # PLOT CLICK OBSERVER   ----------------
  observeEvent(input$plot_click, handlerExpr = {
    print("tagCellServer 3: plot_click event observer")
    if(debug_messages) print("- Plot clicked")
    shinyjs::disable("next_cell")
    shinyjs::disable("prev_cell")
    shinyjs::disable("prev_ucid")
    shinyjs::disable("next_ucid")
    shinyjs::disable("moreControls")
    
    closest_to <- function(closest_to, from_array){
      if(debug_messages) print(paste(">> Closest to:", closest_to, "from array:", paste(from_array, collapse = ", ")))
      index <- which.min(abs(from_array - closest_to))
      return(from_array[index])
    }
    
    if(debug_messages) print(paste("-- Clicked point:", input$plot_click$x))
    
    ith_cell <- reactive_values$ith_cell                                        # Get the current reactive cell number
    ith_ucid_t.frame <- as.character(d$ucid_t.frame[reactive_values$ith_cell])  # Get ucid_t.frame for that cell
    ith_ucid <- as.character(d$ucid[reactive_values$ith_cell])                  # Get ucid for that cell
    ith_t.frame <- as.character(d$t.frame[reactive_values$ith_cell])            # Get t.frame for that cell
    
    click_t.frame <- closest_to(from_array = d[d$ucid == ith_ucid,]$t.frame,
                                closest_to = input$plot_click$x)
    
    if(debug_messages) print(paste("-- Clicked t.frame:", click_t.frame))
      
    if(click_t.frame == ith_t.frame){
      if(debug_messages) print("-- t.frame unchanged")
      shinyjs::enable("next_cell")
      shinyjs::enable("prev_cell")
      shinyjs::enable("prev_ucid")
      shinyjs::enable("next_ucid")
      shinyjs::enable("moreControls")
    } else {
      if(debug_messages) print("-- t.frame changed, saving tag selection")
      ith_cell_tags <- list()
      for(tag_group in 1:length(names(cell_tags)))      # For each tag group
        input[[names(cell_tags)[tag_group]]] ->         # Get the currently selected values array
        ith_cell_tags[[names(cell_tags)[tag_group]]]    # Store it in a list element appropriately named 
      
      reactive_values$selected_cell_tags[[ith_ucid_t.frame]] <- ith_cell_tags  # Save the tag list to a UCID name element in a reactive values list.
      
      next_ith_cell <- which(d$t.frame == click_t.frame & d$ucid == ith_ucid)  # Get the index row for the clicked t.frame
      reactive_values$ith_cell <- next_ith_cell                                # Update the ith_cell reactive value
    }
  })
  
  # BUTTON 1.1: NEXT  ----------------
  ## Input: input$next_cell
  ## Output reactive_values: $selected_cell_tags $ith_cell
  shiny::observeEvent(
    eventExpr = input$next_cell,
    handlerExpr = {
      print("tagCellServer 4: next_cell event observer")
      if(debug_messages) print("- Next cell requested, saving current tags...")
      shinyjs::disable("next_cell")
      shinyjs::disable("prev_cell")
      shinyjs::disable("prev_ucid")
      shinyjs::disable("next_ucid")
      shinyjs::disable("moreControls")
      
      ith_cell <- reactive_values$ith_cell                                 # Get the current reactive cell number
      ith_ucid <- as.character(d$ucid_t.frame[reactive_values$ith_cell])   # Get ucid for that cell
      
      if(debug_messages) print(paste("-- Saving tag selection for current cell with row index:", ith_cell))
      ith_cell_tags <- list()
      for(tag_group in 1:length(names(cell_tags)))      # For each tag group
        input[[names(cell_tags)[tag_group]]] ->         # Get the currently selected values array
          ith_cell_tags[[names(cell_tags)[tag_group]]]  # Store it in a list element appropriately named 
      
      # reactive_values$ith_ucid <- as.character(d$ucid[reactive_values$ith_cell])  # Save the ucid
      reactive_values$selected_cell_tags[[ith_ucid]] <- ith_cell_tags             # Save the tag list to a UCID name element in a reactive values list.
      
      if(debug_messages) print(paste("-- Next cell row index:", ith_cell + 1))
      
      # Handle previous > total
      if(ith_cell == nrow(cdata)){
        showNotification("There is no next cell, staying at the current one.", type = "warning")
        shinyjs::delay(300, expr = {
          shinyjs::enable("prev_cell")
          shinyjs::enable("next_cell")
          shinyjs::enable("prev_ucid")
          shinyjs::enable("next_ucid")
          shinyjs::enable("moreControls")
        })
      } else {
        reactive_values$ith_cell <- ith_cell + 1                     # Update the ith_cell reactive value
      }
    })
  
  # BUTTON 1.2: PREVIOUS  ----------------
  shiny::observeEvent(
    eventExpr = input$prev_cell,
    handlerExpr = {
      print("tagCellServer 5: prev_cell event observer")
      if(debug_messages) print("- Previous cell requested...")
      shinyjs::disable("prev_cell")
      shinyjs::disable("next_cell")
      shinyjs::disable("prev_ucid")
      shinyjs::disable("next_ucid")
      shinyjs::disable("moreControls")
      
      ith_cell <- reactive_values$ith_cell                               # Get the current reactive cell number
      ith_ucid <- as.character(d$ucid_t.frame[reactive_values$ith_cell]) # Get ucid for that cell
      
      if(debug_messages) print(paste("-- Saving tag selection for current cell with row index:", ith_cell))
      ith_cell_tags <- list()
      for(tag_group in 1:length(names(cell_tags)))      # For each tag group
        input[[names(cell_tags)[tag_group]]] ->         # Get the currently selected values array
          ith_cell_tags[[names(cell_tags)[tag_group]]]  # Store it in a list element appropriately named 
      
      reactive_values$selected_cell_tags[[ith_ucid]] <- ith_cell_tags  # Save the tag list to a UCID name element in a reactive values list.
      
      if(debug_messages) print(paste("-- Next cell row index:", ith_cell - 1))
      
      # Handle previous < 1
      if(ith_cell == 1){
        if(debug_messages) print("-- There is no previous cell, staying at the current one.")
        showNotification("There is no previous cell, staying at the current one.", type = "warning")
        shinyjs::delay(300, expr = {
          shinyjs::enable("prev_cell")
          shinyjs::enable("next_cell")
          shinyjs::enable("prev_ucid")
          shinyjs::enable("next_ucid")
          shinyjs::enable("moreControls")
        })
      } else {
        if(debug_messages) print(paste("-- Moving on to cell with row index:", ith_cell - 1))
        reactive_values$ith_cell <- ith_cell - 1                   # Update the ith_cell reactive value
      }
    })
  
  # BUTTON 2.1: NEXT UCID  ----------------
  shiny::observeEvent(
    eventExpr = input$next_ucid,
    handlerExpr = {
      print("tagCellServer 6: next_ucid event observer")
      if(debug_messages) print("- Next ucid requested, saving current tags...")
      shinyjs::disable("next_ucid")
      shinyjs::disable("prev_ucid")
      shinyjs::disable("next_cell")
      shinyjs::disable("prev_cell")
      shinyjs::disable("moreControls")
      
      ith_cell <- reactive_values$ith_cell                                 # Get the current reactive cell number
      ith_ucid <- as.character(d$ucid_t.frame[reactive_values$ith_cell])   # Get ucid_t.frame for that cell
      
      if(debug_messages) print(paste("-- Saving tag selection for current cell with row index:", ith_cell))
      ith_cell_tags <- list()
      for(tag_group in 1:length(names(cell_tags)))      # For each tag group
        input[[names(cell_tags)[tag_group]]] ->         # Get the currently selected values array
        ith_cell_tags[[names(cell_tags)[tag_group]]]  # Store it in a list element appropriately named 
      
      reactive_values$selected_cell_tags[[ith_ucid]] <- ith_cell_tags  # Save the tag list to a UCID name element in a reactive values list.
      
      # Skip to the next UCID
      ucid.oi <- as.character(d$ucid[reactive_values$ith_cell])   # Get bare ucid for the current cell
      ucid.oi.index <- match(ucid.oi, ucid.unique)
      ucid.next <- ucid.unique[ucid.oi.index + 1]                 # Get the next ucid
      ucid.next.index <- match(ucid.next, d$ucid)                 # Get the next ucid's row index
      if(debug_messages) print(paste("-- Next cell row index:", ucid.next.index))
      
      # Handle next > total
      if(ucid.oi.index >= length(ucid.unique)){
        showNotification("--- There is no next ucid, staying at the current one.", type = "warning")
        shinyjs::delay(300, expr = {
          shinyjs::enable("prev_cell")
          shinyjs::enable("next_cell")
          shinyjs::enable("prev_ucid")
          shinyjs::enable("next_ucid")
          shinyjs::enable("moreControls")
        })
      } else {
        showNotification("--- Moving to next ucid.", duration = 1)
        reactive_values$ith_cell <- ucid.next.index               # Update the ith_cell reactive value
      }
    })
  
  # BUTTON 2.2: PREVIOUS UCID ----------------
  shiny::observeEvent(
    eventExpr = input$prev_ucid,
    handlerExpr = {
      print("tagCellServer 7: prev_ucid event observer")
      if(debug_messages) print("- Previous ucid requested...")
      shinyjs::disable("prev_ucid")
      shinyjs::disable("next_ucid")
      shinyjs::disable("prev_cell")
      shinyjs::disable("next_cell")
      shinyjs::disable("moreControls")
      
      ith_cell <- reactive_values$ith_cell                               # Get the current reactive cell number
      ith_ucid <- as.character(d$ucid_t.frame[reactive_values$ith_cell]) # Get ucid for that cell
      if(debug_messages) print(paste("-- Saving tag selection for current cell with row index:", ith_cell))
      
      ith_cell_tags <- list()
      for(tag_group in 1:length(names(cell_tags)))      # For each tag group
        input[[names(cell_tags)[tag_group]]] ->         # Get the currently selected values array
        ith_cell_tags[[names(cell_tags)[tag_group]]]  # Store it in a list element appropriately named 
      
      reactive_values$selected_cell_tags[[ith_ucid]] <- ith_cell_tags  # Save the tag list to a UCID name element in a reactive values list.
      
      # Skip to the previous UCID
      ucid.oi <- as.character(d$ucid[reactive_values$ith_cell])   # Get bare ucid for the current cell
      ucid.oi.index <- match(ucid.oi, ucid.unique)                # Get it's index in the distinct ucid list 
      ucid.next <- ucid.unique[ucid.oi.index - 1]                 # Get the previous unique ucid
      ucid.next.index <- match(ucid.next, d$ucid)                 # Get the previous ucid's row index
      if(debug_messages) print(paste("-- Next cell row index:", ucid.next.index))
      
      # Handle next > total
      if(ucid.oi.index == 1){
        showNotification("--- There is no previous ucid, staying at the current one.", type = "warning")
        shinyjs::delay(300, expr = {
          shinyjs::enable("prev_cell")
          shinyjs::enable("next_cell")
          shinyjs::enable("prev_ucid")
          shinyjs::enable("next_ucid")
          shinyjs::enable("moreControls")
        })
      } else {
        showNotification("--- Moving to previous ucid.", duration = 1)
        reactive_values$ith_cell <- ucid.next.index               # Update the ith_cell reactive value
      }
    })
  
  # SIDE EFFECTS FOR PREV/NEXT BUTTON  ----------------
  ## Input reactive_values: $ith_cell
  ## Output reactive_values: 
  ## Isolated reactive_values: $selected_cell_tags
  shiny::observe({
    print("tagCellServer 8: ith_cell reactive value observer")
    shinyjs::disable("prev_cell")
    shinyjs::disable("next_cell")
    shinyjs::disable("prev_ucid")
    shinyjs::disable("next_ucid")
    shinyjs::disable("moreControls")
    
    ith_cell <- reactive_values$ith_cell
    ith_ucid <- as.character(d$ucid_t.frame[ith_cell])
    selected_cell_tags <- isolate(reactive_values$selected_cell_tags)
    if(debug_messages) print(paste("-- Updating tag selection for next or previous cell with row index:", ith_cell))
    
    if(ith_ucid %in% names(selected_cell_tags)){
      if(debug_messages) print("--- UCID tag found")
      selected_cell_tags <- selected_cell_tags[[ith_ucid]]
      for(tag_group in names(cell_tags)){
        if(tag_group %in% names(selected_cell_tags)){
          # shiny::updateSelectInput(session,
          shiny::updateCheckboxGroupInput(session,
                                          inputId = tag_group,
                                          choices = cell_tags[[tag_group]],
                                          selected = selected_cell_tags[[tag_group]])
        } else {
          # shiny::updateSelectInput(session,
          shiny::updateCheckboxGroupInput(session,
                                          inputId = tag_group,
                                          choices = cell_tags[[tag_group]],
                                          selected = NULL)
        }
      }
    } else {
      if(debug_messages) print("--- UCID not yet tagged")
      for(tag_group in names(cell_tags)){
        # shiny::updateSelectInput(session,
        # shiny::updateSelectInput(session,
        shiny::updateCheckboxGroupInput(session,
                                        inputId = tag_group,
                                        choices = cell_tags[[tag_group]],
                                        selected = NULL)
      }
    }
    
    shinyjs::delay(300, expr = {
      shinyjs::enable("prev_cell")
      shinyjs::enable("next_cell")
      shinyjs::enable("prev_ucid")
      shinyjs::enable("next_ucid")
      shinyjs::enable("moreControls")
      
    })
  })
  
  # BUTTON OBSERVER 3: EXIT  ----------------
  observeEvent(
    # Acción al apretar el botón de cerrar la app
    eventExpr = input$quit,
    handlerExpr = {
      writeLines("\n- Quit event fired")

      if(debug_messages) print(paste("-- Saving progress to file:", tmp_output_file))
      
      table_output <- reactive_values$selected_cell_tags %>% bind_rows(.id = "ucid_t.frame")
      
      if(nrow(table_output) > 0){
        
        table_output <- separate(table_output, ucid_t.frame, c("ucid", "t.frame")) %>% 
          mutate(ucid = as.integer(ucid), t.frame = as.integer(t.frame)) %>% 
          left_join(unique(select(d, ucid, pos, cellID)))
        
        table_output %>% readr::write_csv(path = tmp_output_file)
        
      } else {
        
        table_output <- data.frame()
        
      }
      
      if(debug_messages) print("-- Returning progress to output:")
      stopApp(table_output)
    }
  )
  
  # BUTTON OBSERVER 4: SAVE  ----------------
  observeEvent(
    # Acción al apretar el botón de cerrar la app
    eventExpr = input$save,
    handlerExpr = {
      writeLines("\n- Save event fired")
      
      table_output <- reactive_values$selected_cell_tags %>% 
        bind_rows(.id = "ucid_t.frame")  #%>% mutate(ucid = as.numeric(ucid_t.frame))
      
      if(nrow(table_output) > 0){
        table_output <- separate(table_output, ucid_t.frame, c("ucid", "t.frame")) %>% 
          mutate(ucid = as.integer(ucid), t.frame = as.integer(t.frame)) %>% 
          left_join(select(d, ucid, pos, cellID))
        showNotification(paste("-- Saving progress to file:", tmp_output_file), duration = 4, type = "message")
      } else {
        table_output <- data.frame(message = "No annotations yet...")
        showNotification(paste("-- No annotations yet, nothing was saved."), duration = 4, type = "message")
      }
      
      readr::write_csv(table_output, path = tmp_output_file)
      
    }
  )
  
  ### OUTPUT OBSERVERS and RENDERERS  ----------------
  # Reactive TABLE 1: annotation progress  ----------------
  ## Input reactive_values: $selected_cell_tags
  ## Output reactive_values: 
  ## Isolated reactive_values: $selected_cell_tags
  output$saved_annotations <- shiny::renderTable({
    print("tagCellServer 9: selected_cell_tags reactive table observer")
    if(debug_messages) print("- Rendering table 1")
    
    table_output <- reactive_values$selected_cell_tags %>% 
      data.table::rbindlist(idcol = "ucid_t.frame", fill=TRUE)
      # bind_rows(.id = "ucid_t.frame")  #%>% mutate(ucid = as.numeric(ucid_t.frame))
    
    if(nrow(table_output) > 0){
      table_output <- separate(table_output, ucid_t.frame, c("ucid", "t.frame")) %>% 
        mutate(ucid = as.integer(ucid), t.frame = as.integer(t.frame)) %>% 
        left_join(unique(select(d, ucid, pos, cellID)))
    } else {
      table_output <- data.frame(message = "No annotations yet...")
    }
    
    table_output
  })
  
  # Reactive TEXT 1: current UCID and t.frame  ----------------
  output$cell_ith <- shiny::renderText({
    ith_ucid <- d$ucid[reactive_values$ith_cell]
    
    tag_line <- paste(
      shiny::isolate(reactive_values$ith_cell),
      ith_ucid,
      # paste(unlist(reactive_values$selected_cell_tags[[ith_ucid]]), collapse = "; "),
      sep = ", "
    )
    
    # write(tag_line, file=tmp_csv_output,append=TRUE)
    
    paste(
    "ucid: ", d[reactive_values$ith_cell, c("ucid")],
    "\nt.frame: ", d[reactive_values$ith_cell, c("t.frame")]
    )
  })
  
  # Reactive TEXT 2: hover info  ----------------
  output$hover_info <- renderText({
    tryCatch(
      expr = {
        paste0("x=", signif(input$plot_hover$x, 3), "\t y=", signif(input$plot_hover$y, 3))
      },
      error = function(cond) return("Waiting for valid mouse hover...")
    )
  })
  
  # Reactive IMAGE 1: magickCell  ----------------
  output$pics <- shiny::renderImage({
    print("tagCellServer 10: ith_cell reactive image observer")
    if(debug_messages) print("- Rendering image 1")
    
    # Make the image match the plot's width
    if(is.null(cell_resize)){
      output_plot_width <- session$clientData$output_plot_width
      cell_resize <- output_plot_width/length(tag_channels_select)
    }
    # session$clientData$output_plot_height
    
    if(nrow(d) > 0) {
      if(debug_messages) print("-- Selection not empty: magick!")
      # cdata.selected <- d[d$ucid == d$ucid[reactive_values$ith_cell],]
      cdata.selected <- d[reactive_values$ith_cell,]
      magick.cell <-  magickCell(cdata = cdata.selected, 
                                 p,
                                 # ch=input$image_channel, 
                                 # cell_resize=cell_resize,
                                 cell_resize=cell_resize,
                                 ch=tag_channels_select, 
                                 n = n_max, 
                                 equalize_images = equalize_images,
                                 normalize_images = normalize_images,
                                 boxSize = tag_box_size, 
                                 return_single_imgs = T, 
                                 return_ucid_df = T)
      tmpimage <- magick.cell$img
      
      if(debug_messages) print(paste("--", magick.cell$ucids))
    } else {
      # Output white if selection is empty
      if(debug_messages) print("-- Selection is empty")
      tmpimage <- magick::image_blank(100,10,color = "white") %>% image_annotate(text = "Empty set")
    }
    
    tmpfile <- magick::image_write(tmpimage, tempfile(fileext='jpg'), format = 'jpg')
    
    list(src = tmpfile, 
         contentType = "image/jpeg")
  }, deleteFile=TRUE)
  
  # Reactive PLOT: user plot  ----------------
  output$plot <- shiny::renderPlot({
    print("tagCellServer 11: ith_cell reactive user plot observer")
    if(debug_messages) print("- Rendering plot 1")
    
    ith_ucid <- as.character(d$ucid[reactive_values$ith_cell])
    ith_t.frame <- as.character(d$t.frame[reactive_values$ith_cell])
    
    if(debug_messages) print(paste("-- Current reactive_values$ith_cell:", reactive_values$ith_cell))
    if(debug_messages) print(paste("-- Current ith_ucid:", ith_ucid))
    
    ucid_data <- filter(cdata, ucid %in% ith_ucid)
    
    if(is.null(tag_ggplot)){
      print("tagCellServer 11: no tag_ggplot object provided, rendering defult plot!")
      tag_ggplot <- ggplot() +
        geom_line(aes(x=t.frame, y=a.tot)) + 
        geom_vline(xintercept = as.numeric(ith_t.frame), color = "black")
      tag_ggplot_render <- tag_ggplot %+% ucid_data
    } else {
      # Add data
      tag_ggplot_render <- tag_ggplot %+% ucid_data
      
      # Add current t.frame
      if(debug_messages) print(paste("-- adding geom_vline to plot:"))
      tag_ggplot_render <- tag_ggplot_render + geom_vline(xintercept = as.numeric(ith_t.frame), 
                                                          color = "black")
      
      # Add annotations
      if(debug_messages) print(paste("-- generating selected_cell_tags"))
      # if(debug_messages) print(names(reactive_values$selected_cell_tags))
      # if(debug_messages) print(data.table::rbindlist(reactive_values$selected_cell_tags, idcol = "ucid_t.frame"))
      table_output <- reactive_values$selected_cell_tags %>% 
        data.table::rbindlist(idcol = "ucid_t.frame", fill=TRUE)
        # bind_rows(.id = "ucid_t.frame")  #%>% mutate(ucid = as.numeric(ucid_t.frame))
      
      # if(debug_messages) print(table_output)
      if(nrow(table_output) > 0){
        if(debug_messages) print(paste("-- found annotations for plot, processing..."))
        table_output <- separate(table_output, ucid_t.frame, c("ucid", "t.frame")) %>% 
          mutate(ucid = as.integer(ucid), 
                 t.frame = as.integer(t.frame)) %>% 
          left_join(d[, c("ucid", "pos", "cellID", reactive_values$click_vars$yvar)]) %>% 
          filter(ucid == ith_ucid)
        
        table_output_longer <- table_output %>%
          select(-ucid, -cellID, -pos) %>%
          mutate_at(
            dplyr::vars(tidyselect::any_of(names(cell_tags))),
            as.character
          ) %>%
          pivot_longer(-t.frame,
                       names_to = "categoria",
                       values_to = "valor",
                       values_drop_na = TRUE)
        
        if(debug_messages) print(paste("-- adding geom_vline to plot:"))
        tag_ggplot_render <- tag_ggplot_render + geom_vline(data = table_output_longer,
                                                            aes(xintercept = t.frame,
                                                                color = interaction(categoria, valor, sep = ": "),
                                                                # linetype = valor,
                                                                # text = paste(categoria, valor, sep = ": ")
                                                                ),
                                                            size = 2, linetype = 2) +
          # ggplot2::guides(text = FALSE) +  # http://www.sthda.com/english/wiki/ggplot2-legend-easy-steps-to-change-the-position-and-the-appearance-of-a-graph-legend-in-r-software
          theme(legend.position = "bottom", legend.title = element_blank())
      }
    }
    
    # Render
    if(debug_messages) print("-- Rendering plot")
    tag_ggplot_render
  })
}
gerbeldo/tidycell documentation built on Aug. 15, 2022, 2:35 p.m.