# # This is the server logic of a Shiny web application. You can run the # application by clicking 'Run App' above. # # Find out more about building applications with Shiny here: # # http://shiny.rstudio.com/ # ###########3 devtools::install_github("apache/arrow/r", ref = "tags/apache-arrow-14.0.0", subdir = "arrow/r") source("./server-helper.R") shinyServer(function(input, output, session) { options(shiny.verbose = TRUE) #options(shiny.error = function() { # traceback() # stopApp() #}) ###################### # REACTIVES VALUES # ###################### # Reactive values created to update the current range of the main slider input #slider_range <- reactiveValues(min_value = 1, max_value = 2) # Reactive value created to keep updated the selected precomputed clusters_labels artifact precomputed_clusters <- reactiveValues(selected = NULL) # Reactive value created to keep updated the selected clustering option clustering_options <- reactiveValues(selected = "no_clusters") # Reactive value created to configure the graph brush ranges <- reactiveValues(x = NULL, y = NULL) # Reactive value created to configure clusters options clusters_config <- reactiveValues( metric_hdbscan = DEFAULT_VALUES$metric_hdbscan, min_cluster_size_hdbscan = DEFAULT_VALUES$min_cluster_size_hdbscan, min_samples_hdbscan = DEFAULT_VALUES$min_samples_hdbscan, cluster_selection_epsilon_hdbscan = DEFAULT_VALUES$cluster_selection_epsilon_hdbscan ) # Reactive values created to configure the appearance of the projections graph. config_style <- reactiveValues( path_line_size = DEFAULT_VALUES$path_line_size, path_alpha = DEFAULT_VALUES$path_alpha, point_alpha = DEFAULT_VALUES$point_alpha, point_size = DEFAULT_VALUES$point_size ) # Reactive value created to store time series selected variables ts_variables <- reactiveValues(selected = NULL) # Reactive value created to store the encoder_input X <- reactiveVal() # Reactive value created to store encoder artifact stride enc_ar_stride <- eventReactive(enc_ar(), { stride = ceiling(enc_ar()$metadata$stride/2) }) # Time series artifact ts_ar <- eventReactive( input$dataset, { req(input$dataset) ar <- api$artifact(input$dataset, type='dataset') on.exit({print("eventReactive ts_ar -->"); flush.console()}) ar }, label = "ts_ar") # Reactive value for indexing saved projections plot prj_plot_id <- reactiveVal(0) ################################# # OBSERVERS & OBSERVERS EVENTS # ################################# observeEvent( req(exists("encs_l")), { freezeReactiveValue(input, "dataset") print("observeEvent encoders list enc_l | update dataset list | after freeze") updateSelectizeInput( session = session, inputId = "dataset", choices = encs_l %>% map(~.$metadata$train_artifact) %>% set_names() ) on.exit({print("observeEvent encoders list encs_l | update dataset list -->"); flush.console()}) }, label = "input_dataset" ) observeEvent(input$dataset, { #req(encs_l) print("--> observeEvent input_dataset | update encoder list") print(input$dataset) freezeReactiveValue(input, "encoder") print(paste0("observeEvent input_dataset | update encoders for dataset ", input$dataset)) updateSelectizeInput( session = session, inputId = "encoder", choices = encs_l %>% keep(~ .$metadata$train_artifact == input$dataset) %>% #map(~ .$metadata$enc_artifact) %>% names ) ### TODO: Ver cómo poner bien esta ñapa para que no se actualizen los gráficos antes que el stride updateSliderInput(session, "stride", value = 0) ################ on.exit( {print("observeEvent input_dataset | update encoder list -->"); flush.console()} ) }, label = "input_encoder") observeEvent( input$encoder, { #req(input$dataset, encs_l) #enc_ar = req(enc_ar()) print("--> observeEvent input_encoder | update wlen") freezeReactiveValue(input, "wlen") print("observeEvent input_encoder | update wlen | Before enc_ar") enc_ar = enc_ar() print(paste0("observeEvent input_encoder | update wlen | enc_ar: ", enc_ar)) print("observeEvent input_encoder | update wlen | Set wlen slider values") if (is.null(enc_ar$metadata$mvp_ws)) { print("observeEvent input_encoder | update wlen | Set wlen slider values from w | ") enc_ar$metadata$mvp_ws = c(enc_ar$metadata$w, enc_ar$metadata$w) } print(paste0("observeEvent input_encoder | update wlen | enc_ar$metadata$mvp_ws ", enc_ar$metadata$mvp_ws )) wmin <- enc_ar$metadata$mvp_ws[1] wmax <- enc_ar$metadata$mvp_ws[2] wlen <- enc_ar$metadata$w print(paste0("observeEvent input_encoder | update wlen | Update slider input (", wmin, ", ", wmax, " ) -> ", wlen )) updateSliderInput(session = session, inputId = "wlen", min = wmin, max = wmax, value = wlen ) updateSliderInput( session = session, inputId = "stride", min = 1, max = input$wlen, value = enc_ar_stride() ) on.exit({print("observeEvent input_encoder | update wlen -->"); flush.console()}) } ) # Obtener el valor de stride enc_ar_stride = reactive({ print("--> reactive enc_ar_stride") stride = ceiling(enc_ar()$metadata$mvp_ws[2]/2) #<- enc_ar()$metadata$stride on.exit({print(paste0("reactive_enc_ar_stride | --> ", stride)); flush.console()}) stride }) observeEvent(input$wlen, { req(input$wlen) print(paste0("--> observeEvent input_wlen | update slide stride value | wlen ", input$wlen)) tryCatch({ old_value = input$stride if (input$stride == 0 | input$stride == 1){ old_value = enc_ar_stride() print(paste0("enc_ar_stride: ", old_value)) } freezeReactiveValue(input, "stride") print(paste0("oserveEvent input_wlen | update slide stride value | Update stride to ", old_value)) updateSliderInput( session = session, inputId = "stride", min = 1, max = input$wlen, value = ifelse(old_value <= input$wlen, old_value, 1) ) }, error = function(e){ print(paste0("observeEvent input_wlen | update slide stride value | Error | ", e$message)) }, warning = function(w) { message(paste0("observeEvent input_wlen | update slide stride value | Warning | ", w$message)) } ) on.exit({print(paste0( "observeEvent input_wlen | update slide stride value | Finally | wlen min ", 1, " max ", input$wlen, " current value ", input$stride, " -->")); flush.console()}) }) # Update "metric_hdbscan" selectInput when the app is loaded observe({ updateSelectInput( session = session, inputId = "metric_hdbscan", choices = names(req(hdbscan_metrics)) ) }) # Update the range of point selection when there is new data # observeEvent(X(), { # #max_ = ts_ar()$metadata$TS$n_samples # max_ = dim(X())[[1]] # freezeReactiveValue(input, "points_emb") # updateSliderInput(session = session, inputId = "points_emb", # min = 1, max = max_, value = c(1, max_)) # }) # Update selected time series variables and update interface config observeEvent(tsdf(), { print("--> observeEvent tsdf | update select variables") on.exit({print("--> observeEvent tsdf | update select variables -->"); flush.console()}) freezeReactiveValue(input, "select_variables") #ts_variables$selected = names(tsdf())[names(tsdf()) != "timeindex"] ts_variables$selected = names(isolate(tsdf())) print(paste0("observeEvent tsdf | select variables ", ts_variables$selected)) updateCheckboxGroupInput( session = session, inputId = "select_variables", choices = ts_variables$selected, selected = ts_variables$selected ) }, label = "select_variables") # Update precomputed_clusters reactive value when the input changes observeEvent(input$clusters_labels_name, { print("--> observe | precomputed_cluster selected ") precomputed_clusters$selected <- req(input$clusters_labels_name) print(paste0("observe | precomputed_cluster selected --> | ", precomputed_cluster$selected)) }) # Update clustering_options reactive value when the input changes observe({ print("--> Observe clustering options") clustering_options$selected <- req(input$clustering_options) print("Observe clustering options -->") }) # Update clusters_config reactive values when user clicks on "calculate_clusters" button observeEvent(input$calculate_clusters, { print("--> observe event calculate_clusters | update clusters_config") clusters_config$metric_hdbscan <- req(input$metric_hdbscan) clusters_config$min_cluster_size_hdbscan <- req(input$min_cluster_size_hdbscan) clusters_config$min_samples_hdbscan <- req(input$min_samples_hdbscan) clusters_config$cluster_selection_epsilon_hdbscan <- req(input$cluster_selection_epsilon_hdbscan) #on.exit({print("observe event calculate_clusters | update clusters_config -->")) }) # Observe the events related to zoom the projections graph observeEvent(input$zoom_btn, { print("--> observeEvent zoom_btn") brush <- input$projections_brush if (!is.null(brush)) { if(isTRUE(input$zoom_btn)){ ranges$x <- c(brush$xmin, brush$xmax) ranges$y <- c(brush$ymin, brush$ymax) }else { ranges$x <- NULL ranges$y <- NULL } } else { ranges$x <- NULL ranges$y <- NULL } }) # Observe the events related to change the appearance of the projections graph observeEvent(input$update_prj_graph,{ style_values <- list(path_line_size = input$path_line_size , path_alpha = input$path_alpha, point_alpha = input$point_alpha, point_size = input$point_size) if (!is.null(style_values)) { config_style$path_line_size <- style_values$path_line_size config_style$path_alpha <- style_values$path_alpha config_style$point_alpha <- style_values$point_alpha config_style$point_size <- style_values$point_size } else { config_style$path_line_size <- NULL config_style$path_alpha <- NULL config_style$point_alpha <- NULL config_style$point_size <- NULL } }) # Update ts_variables reactive value when time series variable selection changes observeEvent(input$select_variables, { ts_variables$selected <- input$select_variables }) # Observe to check/uncheck all variables observeEvent(input$selectall,{ req(tsdf) ts_variables$selected <- names(isolate(tsdf())) if(input$selectall %%2 == 0){ updateCheckboxGroupInput(session = session, inputId = "select_variables", choices = ts_variables$selected, selected = ts_variables$selected) } else { updateCheckboxGroupInput(session = session, inputId = "select_variables", choices = ts_variables$selected, selected = NULL) } }) # Observe to update encoder input (enc_input = X()) observe({ #Event(input$dataset, input$encoder, input$wlen, input$stride, { req(input$wlen != 0, input$stride != 0, input$stride != 1) print(paste0("Check reactiveness | X | wlen, stride |")) if ( is.null(X()) || !identical( input$dataset, isolate(input$dataset)) || !identical(input$encoder, isolate(input$encoder)) || input$wlen != isolate(input$wlen) || input$stride != isolate(input$stride) ) { print("--> ReactiveVal X | Update Sliding Window") print(paste0("reactive X | wlen ", input$wlen, " | stride ", input$stride, " | Let's prepare data")) print("reactive X | SWV") t_x_0 <- Sys.time() enc_input = dvats$exec_with_feather_k_output( function_name = "prepare_forecasting_data", module_name = "tsai.data.preparation", path = file.path(DEFAULT_PATH_WANDB_ARTIFACTS, ts_ar()$metadata$TS$hash), k_output = as.integer(0), print_flag = TRUE, time_flag = TRUE, fcst_history = input$wlen ) t_x_1 <- Sys.time() t_sliding_window_view = t_x_1 - t_x_0 print(paste0("reactive X | SWV: ", t_sliding_window_view, " secs ")) print(paste0("reactive X | Update sliding window | Apply stride ", input$stride," | enc_input ~ ", dim(enc_input), "-->")) print("| Update | X" ) on.exit({print("| Outside| X"); flush.console()}) X(enc_input) } X() }) ############### # REACTIVES # ############### # Get timeseries artifact metadata ts_ar_config = reactive({ print("--> reactive ts_ar_config | List used artifacts") ts_ar = req(ts_ar()) print(paste0("reactive ts_ar_config | List used artifacts | hash", ts_ar$hash)) list_used_arts = ts_ar$metadata$TS list_used_arts$vars = ts_ar$metadata$TS$vars %>% stringr::str_c(collapse = "; ") list_used_arts$name = ts_ar$name list_used_arts$aliases = ts_ar$aliases list_used_arts$artifact_name = ts_ar$name list_used_arts$id = ts_ar$id list_used_arts$created_at = ts_ar$created_at list_used_arts on.exit({print("reactive ts_ar_config -->"); flush.console()}) }) # Get encoder artifact enc_ar <- eventReactive ( input$encoder, { print(paste0("eventReactive enc_ar | Enc. Artifact: ", input$encoder)) result <- tryCatch({ api$artifact(input$encoder, type = 'learner') }, error = function(e){ print(paste0("eventReactive enc_ar | Error: ", e$message)) NULL }) on.exit({print("envent reactive enc_ar -->"); flush.console()}) result }, ignoreInit = T ) # Encoder enc <- eventReactive( enc_ar(), { req(input$dataset, input$encoder) print("--> eventReactive enc | load encoder ") encoder_artifact <- enc_ar() enc <- py_load_object( file.path( DEFAULT_PATH_WANDB_ARTIFACTS, encoder_artifact$metadata$ref$hash ) ) on.exit({print("eventReactive enc | load encoder -->"); flush.console()}) enc }) embs <- reactive({ req(X(), enc_l <- enc()) print("--> reactive embs | get embeddings") if (torch$cuda$is_available()){ print(paste0("CUDA devices: ", torch$cuda$device_count())) } else { print("CUDA NOT AVAILABLE") } t_embs_0 <- Sys.time() print( paste0( "reactive embs | get embeddings | Just about to get embedings. Device number: ", torch$cuda$current_device() ) ) print("reactive embs | get embeddings | Get batch size and dataset") dataset_logged_by <- enc_ar()$logged_by() bs = dataset_logged_by$config$batch_size stride = input$stride print(paste0("reactive embs | get embeddings (set stride set batch size) | Stride ", input$stride, " | batch size: ", bs )) enc_input = X() #chunk_max = 10000000 #shape <- dim(enc_input) #print(paste0("reactive embs | get embeddings (set stride set batch size) | enc_input shape: ", shape )) #chunk_size_ = min(shape[1]*shape[2],chunk_max/(shape[1]*shape[2])) #N = max(3200,floor(chunk_size_/32)) chunk_size = 10000000 #N*32 #print(paste0("reactive embs | get embeddings (set stride set batch size) | Chunk_size ", chunk_size, " | shape[1]*shape[2]: ", shape[1]*shape[2] )) print(paste0("reactive embs | get embeddings (set stride set batch size) | Chunk_size ", chunk_size)) # python_string = paste0(" #import dvats.all cpu_flag = ifelse(input$cpu_flag == "CPU", TRUE, FALSE) result = dvats$get_enc_embs_set_stride_set_batch_size( X = X(), print_flag = TRUE, enc_learn = enc_l, stride = input$stride, batch_size = bs, cpu = cpu_flag, print_flag = FALSE, time_flag = TRUE, chunk_size = chunk_size, check_memory_usage = TRUE ) #result <- system(python_string) t_embs_1 <- Sys.time() diff <- t_embs_1 - t_embs_0 diff_secs <- as.numeric(diff, units = "secs") diff_mins <- as.numeric(diff, units = "mins") print(paste0("get_enc_embs total time: ", diff_secs, " secs thus ", diff_mins, " mins")) X <- NULL gc(verbose=TRUE) on.exit({print("reactive embs | get embeddings -->"); flush.console()}) result }) prj_object_cpu <- reactive({ embs = req(embs(), input$dr_method) embs = embs[complete.cases(embs),] print("--> prj_object") #print(embs) #-- #print(paste0("--> prj_object | UMAP params ", str(umap_params_))) print("--> prj_object | UMAP params ") res = switch( input$dr_method, #### Comprobando parametros para saber por qué salen diferentes los embeddings ######### Comprobando los parámetros #UMAP = dvats$get_UMAP_prjs(input_data = embs, cpu=F, n_neighbors = 15, min_dist = 0.1, random_state=as.integer(1234)), UMAP = dvats$get_UMAP_prjs( input_data = embs, cpu = TRUE, print_flag = TRUE, n_neighbors = input$prj_n_neighbors, min_dist = input$prj_min_dist, random_state= as.integer(input$prj_random_state) ), TSNE = dvats$get_TSNE_prjs( X = embs, cpu = TRUE, random_state=as.integer(input$prj_random_state) ), PCA = dvats$get_PCA_prjs( X = embs, cpu = TRUE, random_state=as.integer(input$prj_random_state) ) ) res = res %>% as.data.frame # TODO: This should be a matrix for improved efficiency colnames(res) = c("xcoord", "ycoord") on.exit({print(" prj_object -->"); flush.console()}) flush.console() #browser() res }) prj_object <- reactive({ req(embs(), input$dr_method) print("--> prj_object") t_prj_0 = Sys.time() embs = req(embs()) print("prj_object | Before complete cases ") embs = embs[complete.cases(embs),] #print(embs) #-- #print(paste0("--> prj_object | UMAP params ", str(umap_params_))) print("prj_object | Before switch ") cpu_flag = ifelse(input$cpu_flag == "CPU", TRUE, FALSE) res = switch( input$dr_method, #### Comprobando parametros para saber por qué salen diferentes los embeddings ######### Comprobando los parámetros #UMAP = dvats$get_UMAP_prjs(input_data = embs, cpu=F, n_neighbors = 15, min_dist = 0.1, random_state=as.integer(1234)), UMAP = dvats$get_UMAP_prjs( input_data = embs, cpu = cpu_flag, print_flag = TRUE, n_neighbors = input$prj_n_neighbors, min_dist = input$prj_min_dist, random_state= as.integer(input$prj_random_state) ), TSNE = dvats$get_TSNE_prjs( X = embs, cpu=FALSE, random_state=as.integer(input$prj_random_state) ), PCA = dvats$get_PCA_prjs( X = embs, cpu=FALSE, random_state=as.integer(input$prj_random_state) ) ) res = res %>% as.data.frame # TODO: This should be a matrix for improved efficiency colnames(res) = c("xcoord", "ycoord") t_prj_1 = Sys.time() on.exit({print(paste0(" prj_object | ", t_prj_1-t_prj_0, " seconds -->")); flush.console()}) flush.console() res }) # Load and filter TimeSeries object from wandb tsdf <- reactive( { req(input$encoder, ts_ar()) ts_ar <- req(ts_ar()) print(paste0("--> Reactive tsdf | ts artifact ", ts_ar)) flush.console() t_init <- Sys.time() path = file.path(DEFAULT_PATH_WANDB_ARTIFACTS, ts_ar$metadata$TS$hash) print(paste0("Reactive tsdf | Read feather ", path )) flush.console() df <- read_feather(path, as_data_frame = TRUE, mmap = TRUE) %>% rename('timeindex' = `__index_level_0__`) t_end = Sys.time() print(paste0("Reactive tsdf | Read feather | Execution time: ", t_end - t_init, " seconds")) flush.console() t_end = Sys.time() on.exit({print(paste0("Reactive tsdf | Column to index | Execution time: ", t_end - t_init, " seconds"));flush.console()}) df }) # Auxiliary object for the interaction ts->projections tsidxs_per_embedding_idx <- reactive({ req(input$wlen != 0, input$stride != 0) get_window_indices(1:nrow(isolate(projections())), w = input$wlen, s = input$stride) }) # Filter the embedding points and calculate/show the clusters if conditions are met. projections <- reactive({ print("--> Projections") req(prj_object(), input$dr_method) #prjs <- req(prj_object()) %>% slice(input$points_emb[[1]]:input$points_emb[[2]]) print("Projections | before prjs") prjs <- prj_object() req(input$dataset, input$encoder, input$wlen, input$stride) print("Projections | before switch") switch(clustering_options$selected, precomputed_clusters = { filename <- req(selected_clusters_labels_ar())$metadata$ref$hash clusters_labels <- py_load_object(filename = file.path(DEFAULT_PATH_WANDB_ARTIFACTS, filename)) #prjs$cluster <- clusters_labels[input$points_emb[[1]]:input$points_emb[[2]]] prjs$cluster <- clusters_labels }, calculate_clusters = { clusters = hdbscan$HDBSCAN( min_cluster_size = as.integer(clusters_config$min_cluster_size_hdbscan), min_samples = as.integer(clusters_config$min_samples_hdbscan), cluster_selection_epsilon = clusters_config$cluster_selection_epsilon_hdbscan, metric = clusters_config$metric_hdbscan )$fit(prjs) score = 0 unique_labels <- unique(clusters$labels_) total_unique_labels <- length(unique_labels) if(total_unique_labels > 1){ score = dvats$cluster_score(prjs, clusters$labels_, TRUE) } print(paste0("Projections | Score ", score)) if (score <= 0) { print(paste0("Projections | Repeat projections with CPU because of low quality clusters | score ", score)) prjs <- prj_object_cpu() clusters = hdbscan$HDBSCAN( min_cluster_size = as.integer(clusters_config$min_cluster_size_hdbscan), min_samples = as.integer(clusters_config$min_samples_hdbscan), cluster_selection_epsilon = clusters_config$cluster_selection_epsilon_hdbscan, metric = clusters_config$metric_hdbscan )$fit(prjs) score = 0 unique_labels <- unique(clusters$labels_) total_unique_labels <- length(unique_labels) if(total_unique_labels > 1){ score = dvats$cluster_score(prjs, clusters$labels_, TRUE) } print(paste0("Projections | Repeat projections with CPU because of low quality clusters | score ", score)) } prjs$cluster <- clusters$labels_ }) on.exit({print("Projections -->"); flush.console()}) prjs }) # Update the colour palette for the clusters update_palette <- reactive({ prjs <- req(projections()) if ("cluster" %in% names(prjs)) { unique_labels <- unique(prjs$cluster) print(unique_labels) ## IF the value "-1" exists, assign the first element of mycolors to #000000, if not, assign the normal colorRampPalette if (as.integer(-1) %in% unique_labels) colour_palette <- append("#000000", colorRampPalette(brewer.pal(12,"Paired"))(length(unique_labels)-1)) else colour_palette <- colorRampPalette(brewer.pal(12,"Paired"))(length(unique_labels)) } else colour_palette <- "red" colour_palette }) color_palete_window_plot <- colorRampPalette( colors = c("blue", "green"), space = "Lab" # Option used when colors do not represent a quantitative scale ) start_date <- reactive({ isolate(tsdf())$timeindex[1] }) end_date <- reactive({ end_date_id = 100000 end_date_id = min(end_date_id, nrow(isolate(tsdf()))) isolate(tsdf())$timeindex[end_date_id] }) ts_plot_base <- reactive({ print("--> ts_plot_base") on.exit({print("ts_plot_base -->"); flush.console()}) start_date =isolate(start_date()) end_date = isolate(end_date()) print(paste0("ts_plot_base | start_date: ", start_date, " end_date: ", end_date)) t_init <- Sys.time() tsdf_ <- isolate(tsdf()) %>% select(ts_variables$selected, - "timeindex") tsdf_xts <- xts(tsdf_, order.by = tsdf()$timeindex) t_end <- Sys.time() print(paste0("ts_plot_base | tsdf_xts time", t_end-t_init)) print(head(tsdf_xts)) print(tail(tsdf_xts)) ts_plt = dygraph( tsdf_xts, width="100%", height = "400px" ) %>% dyRangeSelector(c(start_date, end_date)) %>% dyHighlight(hideOnMouseOut = TRUE) %>% dyOptions(labelsUTC = FALSE ) %>% dyCrosshair(direction = "vertical")%>% dyLegend(show = "follow", hideOnMouseOut = TRUE) %>% dyUnzoom() %>% dyHighlight(highlightSeriesOpts = list(strokeWidth = 3)) %>% dyCSS( textConnection( ".dygraph-legend > span { display: none; } .dygraph-legend > span.highlight { display: inline; }" ) ) }) embedding_ids <- reactive({ print("--> embedding idx") on.exit(print("embedding idx -->")) bp = brushedPoints(prj_object(), input$projections_brush, allRows = TRUE) #%>% debounce(miliseconds) #Wait 1 seconds: 1000 bp %>% rownames_to_column("index") %>% dplyr::filter(selected_ == TRUE) %>% pull(index) %>% as.integer }) window_list <- reactive({ print("--> window_list") on.exit(print("window_list -->")) # Get the window indices req(length(embedding_ids() > 0)) embedding_idxs = embedding_ids() window_indices = get_window_indices(embedding_idxs, input$wlen, input$stride) # Put all the indices in one list and remove duplicates unlist_window_indices = unique(unlist(window_indices)) # Calculate a vector of differences to detect idx where a new window should be created diff_vector <- diff(unlist_window_indices,1) # Take indexes where the difference is greater than one (that represent a change of window) idx_window_limits <- which(diff_vector!=1) # Include the first and last index to have a whole set of indexes. idx_window_limits <- c(1, idx_window_limits, length(unlist_window_indices)) # Create a reduced window list reduced_window_list <- vector(mode = "list", length = length(idx_window_limits)-1) # Populate the first element of the list with the idx of the first window. reduced_window_list[[1]] <- c(unlist_window_indices[idx_window_limits[1]], unlist_window_indices[idx_window_limits[1+1]]) # Populate the rest of the list for (i in 2:(length(idx_window_limits)-1)){ reduced_window_list[[i]]<- c( #unlist_window_indices[idx_window_limits[i]+1], #unlist_window_indices[idx_window_limits[i+1]] as.Date(isolate(tsdf())$timeindex[unlist_window_indices[idx_window_limits[i]+1]]), as.Date(isolate(tsdf())$timeindex[unlist_window_indices[idx_window_limits[i+1]]]) ) } reduced_window_list }) # Generate timeseries data for dygraph dygraph ts_plot <- reactive({ print("--> ts_plot | Before req 1") on.exit({print("ts_plot -->"); flush.console()}) req(tsdf(), ts_variables, input$wlen != 0, input$stride) ts_plt = ts_plot_base() print("ts_plot | bp") #miliseconds <- ifelse(nrow(tsdf()) > 1000000, 2000, 1000) #if (!is.data.frame(bp)) {bp = bp_} print("ts_plot | embedings idxs ") embedding_idxs = embedding_ids() # Calculate windows if conditions are met (if embedding_idxs is !=0, that means at least 1 point is selected) print("ts_plot | Before if") if ((length(embedding_idxs)!=0) & isTRUE(input$plot_windows)) { reduced_window_list = req(window_list()) print(paste0("ts_plot | reduced_window_list[1] = ", reduced_window_list[1])) start_indices = min(sapply(reduced_window_list, function(x) x[1])) end_indices = max(sapply(reduced_window_list, function(x) x[2])) view_size = end_indices-start_indices+1 max_size = 10000 start_date = isolate(tsdf())$timeindex[start_indices] end_date = isolate(tsdf())$timeindex[end_indices] print(paste0("ts_plot | reuced_window_list (", start_date, end_date, ")", "view size ", view_size, "max size ", max_size)) if (view_size > max_size) { end_date = isolate(tsdf())$timeindex[start_indices + max_size - 1] #range_color = "#FF0000" # Red } range_color = "#CCEBD6" # Original # # Plot the windows count = 0 for(ts_idxs in reduced_window_list) { count = count + 1 start_event_date = isolate(tsdf())$timeindex[head(ts_idxs, 1)] end_event_date = isolate(tsdf())$timeindex[tail(ts_idxs, 1)] ts_plt <- ts_plt %>% dyShading( from = start_event_date, to = end_event_date, color = range_color ) ts_plt <- ts_plt %>% dyRangeSelector(c(start_date, end_date)) #%>% dyEvent( # start_event_date, # label = paste0("SW-", count), # labelLoc="bottom" , # strokePattern = "solid", # color = range_color # ) %>% dyEvent( # end_event_date, # label = paste0("SW-",paste0("SW-", count), # labelLoc="bottom", # strokePattern = "solid"), # color = range_color # ) } ts_plt <- ts_plt # NOTE: This code block allows you to plot shadyng at once. # The traditional method has to plot the dygraph n times # (n being the number of rectangles to plot). With the adjacent # code it is possible to plot the dygraph only once. Currently # it does not work well because there are inconsistencies in the # timezones of the time series and shiny (there is a two-hour shift[the current plot method works well]), # which does not allow this method to be used correctly. If that # were fixed in the future everything would work fine. # num_rects <- length(reduced_window_list) # rects_ini <- vector(mode = "list", length = num_rects) # rects_fin <- vector(mode = "list", length = num_rects) # for(i in 1:num_rects) { # rects_ini[[i]] <- head(reduced_window_list[[i]],1) # rects_fin[[i]] <- tail(reduced_window_list[[i]],1) # } # ts_plt <- vec_dyShading(ts_plt,rects_ini, rects_fin,"red", rownames(tsdf())) } ts_plt }) # Get projections plot name for saving prjs_plot_name <- reactive({ dataset_name <- basename(input$dataset) encoder_name <- basename(input$encoder) get_prjs_plot_name(dataset_name, encoder_name, clustering_options$selected, prjs_$cluster, prj_plot_id, input) }) # Get timeserie plot name for saving ts_plot_name <- reactive({ dataset_name <- basename(input$dataset) encoder_name <- basename(input$encoder) get_ts_plot_name(dataset_name, encoder_name, prj_plot_id, input) }) ############# # OUTPUTS # ############# output$windows_plot <- renderPlot({ req(length(embedding_ids()) > 0) reduced_window_list = req(window_list()) # Convertir a fechas POSIXct reduced_window_df <- do.call(rbind, lapply(reduced_window_list, function(x) { data.frame( start = as.POSIXct(isolate(tsdf())$timeindex[x[1]], origin = "1970-01-01"), end = as.POSIXct(isolate(tsdf())$timeindex[x[2]], origin = "1970-01-01") ) })) # Establecer límites basados en los datos first_date = min(reduced_window_df$start) last_date = max(reduced_window_df$end) left = as.POSIXct(isolate(tsdf())$timeindex[1], origin = "1970-01-01") right = as.POSIXct(isolate(tsdf())$timeindex[nrow(isolate(tsdf()))], origin = "1970-01-01") # Configuración del gráfico base par(mar = c(5, 4, 4, 0) + 0.1) #Down Up Left Right plt <- plot( NA, xlim = c(left, right), ylim = c(0, 1), type = "n", xaxt = "n", yaxt = "n", xlab = "", ylab = "", bty = "n") f = "%F %H:%M:%S" axis(1, at = as.numeric(c(left, right)), labels = c(format(first_date, f), format(last_date, f)), cex.axis = 0.7) # Añadir líneas verticales colors = color_palete_window_plot(2) abline( v = as.numeric(reduced_window_df$start), col = rep(colors, length.out = nrow(reduced_window_df)), lwd = 1 ) abline( v = as.numeric(reduced_window_df$end), col = rep(colors, length.out = nrow(reduced_window_df)), lwd = 1 ) segments( x0 = as.numeric(reduced_window_df$start), x1 = as.numeric(reduced_window_df$end), y0 = 0, y1 = 0, col = rep(colors, length.out = nrow(reduced_window_df)), lwd = 1 ) text( x = as.numeric(reduced_window_df$start), y = 0, srt = 90, adj = c(1,0.5), labels = paste0("SW-", seq_len(nrow(reduced_window_df)), format(reduced_window_df$start, f)), cex = 1, xpd = TRUE, col = rep(colors, length.out = nrow(reduced_window_df)) ) points(x = as.numeric(left),y = 0, col = "black", pch = 20, cex = 1) points(x = as.numeric(right),y = 0, col = "black", pch = 20, cex = 1) plt }, height=200 ) output$windows_text <- renderUI({ req(length(embedding_ids()) > 0) reduced_window_list = req(window_list()) # Crear un conjunto de etiquetas de texto con información de las ventanas window_info <- lapply(1:length(reduced_window_list), function(i) { window <- reduced_window_list[[i]] start <- format(as.POSIXct(isolate(tsdf())$timeindex[window[1]], origin = "1970-01-01"), "%b %d") end <- format(as.POSIXct(isolate(tsdf())$timeindex[window[2]], origin = "1970-01-01"), "%b %d") color <- ifelse(i %% 2 == 0, "green", "blue") HTML(paste0("
Window ", i, ": ", start, " - ", end, "
")) }) # Devuelve todos los elementos de texto como una lista de HTML do.call(tagList, window_info) }) # Generate encoder info table output$enc_info = renderDataTable({ selected_encoder_name <- req(input$encoder) on.exit({print("Encoder artiffact -->"); flush.console()}) print(paste0("--> Encoder artiffact", selected_encoder_name)) selected_encoder <- encs_l[[selected_encoder_name]] encoder_metadata <- req(selected_encoder$metadata) print(paste0("Encoder artiffact | encoder metadata ", selected_encoder_name)) encoder_metadata %>%enframe() }) # Generate time series info table output$ts_ar_info = renderDataTable({ ts_ar_config() %>% enframe() }) # Generate projections plot output$projections_plot <- renderPlot({ req(input$dataset, input$encoder, input$wlen != 0, input$stride != 0) print("--> Projections_plot") prjs_ <- req(projections()) print("projections_plot | Prepare column highlights") # Prepare the column highlight to color data if (!is.null(input$ts_plot_dygraph_click)) { selected_ts_idx = which(ts_plot()$x$data[[1]] == input$ts_plot_dygraph_click$x_closest_point) projections_idxs = tsidxs_per_embedding_idx() %>% map_lgl(~ selected_ts_idx %in% .) prjs_$highlight = projections_idxs } else { prjs_$highlight = FALSE } # Prepare the column highlight to color data. If input$generate_cluster has not been clicked # the column cluster will not exist in the dataframe, so we create with the value FALSE if(!("cluster" %in% names(prjs_))) prjs_$cluster = FALSE print("projections_plot | GoGo Plot!") plt <- ggplot(data = prjs_) + aes(x = xcoord, y = ycoord, fill = highlight, color = as.factor(cluster)) + scale_colour_manual(name = "clusters", values = req(update_palette())) + geom_point(shape = 21,alpha = config_style$point_alpha, size = config_style$point_size) + scale_shape(solid = FALSE) + #geom_path(size=config_style$path_line_size, colour = "#2F3B65",alpha = config_style$path_alpha) + guides() + scale_fill_manual(values = c("TRUE" = "green", "FALSE" = "NA"))+ coord_cartesian(xlim = ranges$x, ylim = ranges$y, expand = TRUE)+ theme_void() + theme(legend.position = "none") if (input$show_lines){ #plt <- plt + geom_path(size=config_style$path_line_size, colour = "#2F3B65",alpha = config_style$path_alpha) plt <- plt + geom_path(linewidth=config_style$path_line_size, colour = "#2F3B65",alpha = config_style$path_alpha) } observeEvent(input$savePlot, { plt <- plt + theme(plot.background = element_rect(fill = "white")) ggsave(filename = prjs_plot_name(), plot = plt, path = "../data/plots/") }) #observeEvent(c(input$dataset, input$encoder, clustering_options$selected), { #req(input$dataset, input$encoder) #print("!-- CUDA?: ", torch$cuda$is_available()) #prjs_ <- req(projections()) #filename <- prjs_plot_name() #print(paste("saving embedding plot to ",filename)) #ggsave(filename = filename, plot = plt, path="../data/plots/") #print("Embeding plot saved") #}) plt }) # Render projections plot output$projections_plot_ui <- renderUI( { plotOutput( "projections_plot", click = "projections_click", brush = "projections_brush", height = input$embedding_plot_height ) %>% withSpinner() } ) # Render information about the selected point in the time series graph output$point <- renderText({ req(input$ts_plot_dygraph_click$x_closest_point) ts_idx = which(ts_plot()$ts$x$data[[1]] == input$ts_plot_dygraph_click$x_closest_point) paste0('X = ', strftime(req(input$ts_plot_dygraph_click$x_closest_point), "%F %H:%M:%S"), '; Y = ', req(input$ts_plot_dygraph_click$y_closest_point), '; X (raw) = ', req(input$ts_plot_dygraph_click$x_closest_point)) }) # Render information about the selected point and brush in the projections graph output$projections_plot_interaction_info <- renderText({ xy_str <- function(e) { if(is.null(e)) return("NULL\n") paste0("x=", round(e$x, 1), " y=", round(e$y, 1), "\n") } xy_range_str <- function(e) { if(is.null(e)) return("NULL\n") paste0("xmin=", round(e$xmin, 1), " xmax=", round(e$xmax, 1), " ymin=", round(e$ymin, 1), " ymax=", round(e$ymax, 1)) } paste0( "click: ", xy_str(input$projections_click), "brush: ", xy_range_str(input$projections_brush) ) }) # Generate time series plot output$ts_plot_dygraph <- renderDygraph( { req ( input$dataset, input$encoder, input$wlen != 0, input$stride != 0 ) #print("Saving time series plot") ts_plot <- req(ts_plot()) #save_path <- file.path("..", "data", "plots", ts_plot_name()) #htmlwidgets::saveWidget(ts_plot, file = save_path, selfcontained=TRUE) #print(paste0("Time series plot saved to", save_path)) ts_plot #req(ts_plot()) } ) prjs_plot_name <- reactive({ dataset_name <- basename(input$dataset) encoder_name <- basename(input$encoder) get_prjs_plot_name(dataset_name, encoder_name, clustering_options$selected, prjs_$cluster) }) ts_plot_name <- reactive({ dataset_name <- basename(input$dataset) encoder_name <- basename(input$encoder) get_ts_plot_name(dataset_name, encoder_name) }) })