misantamaria's picture
Hot fix Server.R
edc7df4 verified
raw
history blame
46.2 kB
#
# 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()
#Añadido para Jacinto
path = file.path(DEFAULT_PATH_WANDB_ARTIFACTS, encoder_artifact$metadata$ref$hash)
print(paste0("Reactive enc | Load object ", path ))
flush.console()
#enc_dir= encoder_artifact$download()
#print(paste0("Reactive enc | Load object | enc dir | Test sin root ", enc_dir ))
#enc_dir = encoder_artifact$download(
# root=DEFAULT_PATH_WANDB_ARTIFACTS
#)
#print(paste0("Reactive enc | Load object | enc dir ", enc_dir ))
print(paste0("eventReactive enc | load encoder | Enc. Artifact: ", input$encoder))
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()
#artifact_dir = ts_ar$download(root=DEFAULT_PATH_WANDB_ARTIFACTS)
#print(paste0("Reactive tsdf | Read feather | Downloaded: ", artifact_dir))
print(system('ls -la /.artifacts', intern=TRUE))
print(system('ls -la /.artifacts/mvp-SWV:v1', intern=TRUE))
df <- read_feather(path, as_data_frame = TRUE, mmap = FALSE) %>% 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(
isolate(tsdf())$timeindex[unlist_window_indices[idx_window_limits[1]+1]],
isolate(tsdf())$timeindex[unlist_window_indices[idx_window_limits[2]]]
)
# 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]]
isolate(tsdf())$timeindex[unlist_window_indices[idx_window_limits[i]+1]],
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("<div style='color: ", color, "'>Window ", i, ": ", start, " - ", end, "</div>"))
})
# 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)
})
})