From f4494551de8851460cc4d89c646ee995beca57f1 Mon Sep 17 00:00:00 2001 From: cedlich Date: Thu, 7 Apr 2022 16:41:51 +0200 Subject: [PATCH] first commit --- .DS_Store | Bin 0 -> 8196 bytes Scripts/delta_list.R | 88 ++++++++ Scripts/get_network_layout.R | 45 ++++ Scripts/network_plotter.R | 71 +++++++ Scripts/propagate_label.R | 128 ++++++++++++ cor_cluster_mix.RDS | Bin 0 -> 67 bytes data20.RDS | Bin 0 -> 46268 bytes delta_converter_list.csv | 15 ++ make_data20.R | 7 + shiny_uNetwork.R | 386 +++++++++++++++++++++++++++++++++++ 10 files changed, 740 insertions(+) create mode 100644 .DS_Store create mode 100644 Scripts/delta_list.R create mode 100644 Scripts/get_network_layout.R create mode 100644 Scripts/network_plotter.R create mode 100644 Scripts/propagate_label.R create mode 100644 cor_cluster_mix.RDS create mode 100644 data20.RDS create mode 100644 delta_converter_list.csv create mode 100644 make_data20.R create mode 100644 shiny_uNetwork.R diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..63d18743a12d4cc46ba455ec1e4d72b095714121 GIT binary patch literal 8196 zcmeHLUu+ab82`Sbl-Z@FTmD@CNa=;P5%hrGwYEhlUfa_^1lxFpwiGCLw<}%Q+dXgh zdM%}?M)X(`O`q!8_)RtLC3Lf_0yRnrcoNxHugETmo{yqAc9TZAeUo9rmZ`rUZ-g5 zt{5jJ4U8#F8Pn>gr{l4BS2WW0NZU*_G98O|#G{eUuH7>;3ae>}bsspHn>sUncINpv z<=W6cAE0W;)*UFF>KFYs1PD>i%If>)0vt zj4`HFxrD?4dK@Si6SV4~tYZ~(wmYU(XVX@;Xr(=)$FjJyJM0;g9`7A>or2dV9LF@R z=o(KOn>B3Rv`-C9n68LIE1fYcscKg{nD(SHG$EHKmAlnFtQw=rFzr!}*5gX`zHowR zbL<44`(WDj`tyeU_gf_y8{w87T{m6Mlo=;SXe3jq7m(HsUtijt^rLWB4fU!EW4#eRvQL zVLuMw5gfyln87TbMh}ZPiBtFjzKZAYHGCc4#&_{Oyn-L#hxiG8Dz`7Rz}5qcI7nTb zqh>i5>9?BTV(Ly@Y#=T+|F2y9wn7qc!^TZpnzlt_9eWbD_HM~`-NvZJG!o2_)DVj4(gc|O`^&%Z7>8ImD7x8TgU(QM?LMcXs Xl9ZYJfBqvNxc@o)!TrxsxR1+U-XIPz literal 0 HcmV?d00001 diff --git a/Scripts/delta_list.R b/Scripts/delta_list.R new file mode 100644 index 0000000..9f299aa --- /dev/null +++ b/Scripts/delta_list.R @@ -0,0 +1,88 @@ +to_matrix <- function(df) { + + nm <- df[[1]] + + df %>% select(-1) %>% as.matrix() %>% set_rownames(nm) + +} + +my_quick_mass <- function(x) { + check_chemform(isotopes = isotopes, x)$monoisotopic_mass +} + +K = my_quick_mass("K") +Na = my_quick_mass("Na") +H = my_quick_mass("H") +C13 = 1.003355 + +NH3 = my_quick_mass("NH3") +H2O = my_quick_mass("H2O") + + +delta_list = + c(`Na-H` = Na - H, + `K-H` = K-H, + NH3 = NH3, + `Na-NH4` = Na - NH3 - H, + `K-NH4` = K - NH3 - H, + H2O = H2O, + C13 = C13, + C1H2O2 = my_quick_mass("C1H2O2"), + C2H7N1 = my_quick_mass("C2H7N1"), + C8H6O3 = my_quick_mass("C8H6O3"), + CO2 = my_quick_mass("C1O2"), + Bz = my_quick_mass("C7H5O1"), + Acetonitrile = my_quick_mass("C2H3N1"), + DMSO = my_quick_mass("C2H6O1S1") + ) + + +d1 <- tibble( + adduct = c("H", "Na", "K", "NH4"), + delta1 = c(0, Na-H, K-H, NH3) +) + + + +d2 <- tibble( + gain_loss = c("None", "+DMSO", "+Acetonitrile", "+C2H7N1", "+H2O", "-H2O", "-CO2", "-C1H2O2", "-C8H6O3", "-Bz", "-NH3"), + delta2 = c(0, delta_list[c("DMSO", "Acetonitrile", "C2H7N1", "H2O")], -delta_list[c("H2O", "CO2", "C1H2O2", "C8H6O3", "Bz", "NH3")]) +) + +d3 <- tibble( + isotope = c("M", "M+1", "M+2", "M+3"), + delta3 = C13 * c(0:3) +) + + +format_species <- function(a, gl, iso) { + + case_when( + gl == "None" & iso == "M" ~ sprintf("[%s + %s]", iso, a), + gl == "None" & iso != "M" ~ sprintf("[(%s) + %s]", iso, a), + gl != "None" & iso == "M" ~ sprintf("[%s + %s] %s", iso, a, gl), + TRUE ~ sprintf("[(%s) + %s] %s", iso, a, gl) + ) + +} + +delta_list2 <- + expand_grid( + adduct = c("H", "Na", "K", "NH4"), + gain_loss = c("None", "+DMSO", "+Acetonitrile", "+C2H7N1", "+H2O", "-H2O", "-CO2", "-C1H2O2", "-C8H6O3", "-Bz", "-NH3"), + isotope = c("M", "M+1", "M+2", "M+3") + ) %>% + left_join( + d1, by = "adduct" + ) %>% + left_join( + d2, by = "gain_loss" + ) %>% + left_join( + d3, by = "isotope" + ) %>% + filter(!(gain_loss == "-NH3" & adduct == "NH4")) %>% + mutate( + name2 = format_species(adduct, gain_loss, isotope), + delta = delta1 + delta2 + delta3 + ) diff --git a/Scripts/get_network_layout.R b/Scripts/get_network_layout.R new file mode 100644 index 0000000..58ec930 --- /dev/null +++ b/Scripts/get_network_layout.R @@ -0,0 +1,45 @@ +get_network_layout <- function(obj, clust) { + + # node_cat, edge_cat, node_size, edge_size + + node <- obj$node %>% + filter(clust_id == clust) + + edge <- obj$edge %>% + filter(FEATURE_ID_1 %in% node$FEATURE_ID & FEATURE_ID_2 %in% node$FEATURE_ID) + + coord <- get_layout(edge) + + node %<>% + left_join(coord, by = "FEATURE_ID") + + edge %<>% + left_join(coord, by = c("FEATURE_ID_1" = "FEATURE_ID")) %>% + left_join(coord, by = c("FEATURE_ID_2" = "FEATURE_ID"), suffix = c("", "end")) + + deg <- c(edge$FEATURE_ID_1, edge$FEATURE_ID_2) %>% table() %>% {tibble(FEATURE_ID = names(.), Degree = unname(.))} + + node %<>% + left_join(deg, by = "FEATURE_ID") + + list( + edge = edge, + node = node + ) + +} + + + + + + + + + + + + + + + diff --git a/Scripts/network_plotter.R b/Scripts/network_plotter.R new file mode 100644 index 0000000..faf69f5 --- /dev/null +++ b/Scripts/network_plotter.R @@ -0,0 +1,71 @@ + +gg_network_plotter <- function( + obj, + node_size1 = 10, + node_colour_var = "adduct", + show_text = F, + text_colour_var = "name2", + text_size = 8, + text_colour = "cyan", + edge_colour_var = "Signature", + edge_size = 1 +) + +{ + + node <- obj$node + edge <- obj$edge + + save(list = ls(), file = "bip.RData") + + gg <- ggplot() + + geom_segment( + mapping = aes(x=x, y=y, xend=xend, yend=yend, colour = !!as.name(edge_colour_var)), + data = edge, + size = edge_size + ) + + + geom_point( + data = node, + mapping=aes(x=x, y=y, fill = !!as.name(node_colour_var)), + shape = 21, + size = node_size1, + ) + + + theme_void() + + labs( + title = "COMPOUND_ID %s MZ %.4f RT %.2f" %>% sprintf(node$COMPOUND_ID[1], node$MZ[1], node$RT[1]) + ) + + if(show_text) { + + gg <- gg + + geom_text( + data = node, + mapping=aes(x=x, y=y, label = !!as.name(text_colour_var)), + size = text_size, + colour = text_colour, + ) + } + + + return(gg) + +} + + +plot_cluster <- function(obj, clust) { + + obj %>% + get_network_layout(clust) %>% + gg_network_plotter(show_text = T) + +} + + + + + + + + diff --git a/Scripts/propagate_label.R b/Scripts/propagate_label.R new file mode 100644 index 0000000..c6968e8 --- /dev/null +++ b/Scripts/propagate_label.R @@ -0,0 +1,128 @@ +delta_converter_list <- read_csv("delta_converter_list.csv", show_col_types = FALSE) %>% to_matrix() + +my_label_propagation2 <- function(obj) { + + node <- obj$node %>% + arrange(-mean) + + edge <- obj$edge + + # anchor_node: character[1] (FEATURE_ID) + anchor_node <- node$FEATURE_ID %>% first() + + # initiliase tibbles + nodelist <- anchor_node + done <- character(0) + + + # matrix + node_assign <- + bind_cols( + node %>% select(FEATURE_ID), + map_df(as_tibble(delta_converter_list), ~ rep(0L, nrow(node))) + ) %>% + to_matrix() + + # assume principal node is M+H + node_assign[anchor_node, "H"] <- 1 + + # neighborhood tibble + N <- get_adjacency_tibble(edge) + + + while (length(nodelist) > 0) { + + new_nodelist <- character(0) + + # i: character[1] + for (i in nodelist) { + + # print(paste("i", i)) + + # j character[1] + for(j in N %>% filter(n1==i) %$% n2 %>% setdiff(done)) { + + # print(paste("j", j)) + + node_assign[j,] <- node_assign[i,] + convert_delta_code(N %>% filter(n1==i, n2==j) %$% code) + + new_nodelist <- c(new_nodelist, j) + } + + done <- c(done, i) + } + + done %<>% unique() + + nodelist <- new_nodelist %>% unique() + + + + } + + node_assign %<>% + as_tibble(rownames = "FEATURE_ID") %>% + get_species() + + list( + edge = edge, + node = node %>% left_join(node_assign %>% select(FEATURE_ID, M, adduct, gain_loss, name2), by = "FEATURE_ID"), + decomposition_table = nodelist, + anchor_node = anchor_node + + ) + +} + +get_species <- function(x) { + + + x %>% + mutate( + adduct = sprintf("_Na_%d__K_%d__H_%d_", Na, K, H) %>% + gsub("_[A-Za-z0-9]+_0_", "", .) %>% + gsub("(_1)|(^_)|(_$)", "", .) %>% + # sub("H__NH3", "NH4", .) %>% + sub("__H_-([1-9])", "-\\1H", .) %>% + sub("-1H", "-H", .) %>% + gsub("__", "+", .), + + M = if_else(C13 == 0, "M", sprintf("(M+%d)", C13)), + + gain_loss = sprintf("_NH3_%d__H2O_%d__FA_%d__C2H7N1_%d__C8H6O3_%d__CO2_%d__Bz_%d__ACN_%d__DMSO_%d_", NH3, H2O, C1H2O2, C2H7N1, C8H6O3, CO2, Bz, Acetonitrile, DMSO) %>% + + gsub("_[A-Za-z0-9]+_0_", "", .) %>% + gsub("_([A-Za-z0-9]+)_-([1-9])", "-\\2.\\1", .) %>% + gsub("-1\\.", "-", .) %>% + gsub("(_1)|(^_)|(_$)", "", .) %>% + gsub("__", "+", .) %>% + gsub("_-", "-", .), + + name2 = sprintf("[%s + %s] +%s", M, adduct, gain_loss) %>% + gsub("\\+-", "-", .) %>% + gsub("\\+$", "", .) %>% + trimws() + + + ) + +} + + + +get_adjacency_tibble <- function(edge) { + + adj <- get_adjacency_matrix_delta(edge) %>% t() + + N <- lapply(seq(nrow(adj)), function(i) adj[i,] %>% keep(.!=0)) + + tibble( + n1 = rownames(adj), + n2 = map(N, ~names(.x)), + code = map(N, ~unname(.x)) + ) %>% + unnest(c(n2, code)) + +} + + diff --git a/cor_cluster_mix.RDS b/cor_cluster_mix.RDS new file mode 100644 index 0000000000000000000000000000000000000000..10893300e1b2ac900ba46f5a5fc15865402ff17a GIT binary patch literal 67 zcmb2|=3oE==I#ec2?+^l35f|w32CfGk`d0%cS>{{co-GZSiB0DGXFjKv*^c@IhP(y Uy0YlUoikhv3(mA1FazoZ0PgS_e*gdg literal 0 HcmV?d00001 diff --git a/data20.RDS b/data20.RDS new file mode 100644 index 0000000000000000000000000000000000000000..509d4e5d763cfcb8ec7b9f191274247d4a143690 GIT binary patch literal 46268 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�T^f{W|KMunK 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

7OUj{?}Kkky*loKZE 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 I-YJFx0A{y&kN^Mx literal 0 HcmV?d00001 diff --git a/delta_converter_list.csv b/delta_converter_list.csv new file mode 100644 index 0000000..f3c7b0d --- /dev/null +++ b/delta_converter_list.csv @@ -0,0 +1,15 @@ +Name,Na,K,H,NH3,H2O,C13,C1H2O2,C2H7N1,C8H6O3,CO2,Bz,Acetonitrile,DMSO +Na-H,1,0,-1,0,0,0,0,0,0,0,0,0,0 +K-H,0,1,-1,0,0,0,0,0,0,0,0,0,0 +NH3,0,0,0,1,0,0,0,0,0,0,0,0,0 +Na-NH4,1,0,-1,-1,0,0,0,0,0,0,0,0,0 +K-NH4,0,1,-1,-1,0,0,0,0,0,0,0,0,0 +H2O,0,0,0,0,1,0,0,0,0,0,0,0,0 +C13,0,0,0,0,0,1,0,0,0,0,0,0,0 +C1H2O2,0,0,0,0,0,0,1,0,0,0,0,0,0 +C2H7N1,0,0,0,0,0,0,0,1,0,0,0,0,0 +C8H6O3,0,0,0,0,0,0,0,0,1,0,0,0,0 +CO2,0,0,0,0,0,0,0,0,0,1,0,0,0 +Bz,0,0,0,0,0,0,0,0,0,0,1,0,0 +Acetonitrile,0,0,0,0,0,0,0,0,0,0,0,1,0 +DMSO,0,0,0,0,0,0,0,0,0,0,0,0,1 diff --git a/make_data20.R b/make_data20.R new file mode 100644 index 0000000..7e97a8b --- /dev/null +++ b/make_data20.R @@ -0,0 +1,7 @@ + +cor_cluster_mix <- readRDS("cor_cluster_mix.RDS") + +cl <- cor_cluster_mix$node %>% arrange(-clust_size) %$% clust_id %>% unique() %>% head(100) + +purrr::map(cl %>% head(20), ~get_network_layout(cor_cluster_mix, .x) %>% my_label_propagation2()) %>% + saveRDS("data20.RDS") diff --git a/shiny_uNetwork.R b/shiny_uNetwork.R new file mode 100644 index 0000000..ea14ad1 --- /dev/null +++ b/shiny_uNetwork.R @@ -0,0 +1,386 @@ +rm(list=ls(envir = .GlobalEnv), envir = .GlobalEnv) + +library(magrittr) +library(tidyverse) +library(igraph) +library(shiny) +library(shinythemes) +library(Matrix) +library(readxl) +library(enviPat) + +data("isotopes") + + +dir1 <- "Scripts" + +for (f in list.files(dir1, pattern = "\\.R$")) { + source(file.path(dir1, f)) + +} + +# source("Scripts/make_network.R") +# source("Scripts/delta_list.R") +# source("Scripts/network_plotter.R") + + +# source("Scripts/calc_layout.R") +# source("Scripts/network_bipartite.R") +# source("Scripts/convert_to_adjacency.R") +# +assign("colours1", colours() %>% keep(!grepl("^gr[ea]y", .) & !grepl("[0-9]$", .)) %>% sort(), envir = .GlobalEnv) + + + +ui <- + + fluidPage( + title = "Feature matrix plotter", + sidebarLayout( + sidebarPanel( + h4("Inputs"), + br(), + tabsetPanel( + tabPanel( + title = "Cluster", + br(), + + uiOutput("select_cluster") + ), + + tabPanel( + title = "Nodes", + br(), + + sliderInput( + inputId = "node_size1", + label = "Node size", + value = 10, + min = 1, + step = 1, + max = 20 + ), + + + selectizeInput( + inputId = "node_colour_var", + label = "Choose node colour variable", + choices = c("adduct", "gain_loss"), + selected = c("adduct", "gain_loss")[1], + multiple = F, + width = "200px" + ) + + + ), # end node + + tabPanel( + title = "Edges", + br(), + + sliderInput( + inputId = "edge_size", + label = "Edge size (thickness)", + value = 1, + min = 0.5, + step = 0.5, + max = 5 + ), + + selectizeInput( + inputId = "edge_colour_var", + label = "Choose node colour variable", + choices = c("Signature", "COR"), + selected = c("Signature", "COR")[1], + multiple = F, + width = "200px" + ) + + + ), # end edge + + tabPanel( + title = "Label", + br(), + + radioButtons( + inputId = "show_text", + label = "Show labels", + choices = c("yes", "no"), + selected = "yes", + inline = T + ), + + sliderInput( + inputId = "text_size", + label = "Label size", + value = 5, + min = 1, + step = 0.5, + max = 10 + ), + + selectizeInput( + inputId = "text_var", + label = "Choose node colour variable", + choices = c("FEATURE_ID", "name2"), + selected = "name2", + multiple = F, + width = "200px" + ), + + selectizeInput( + inputId = "text_colour", + label = "Label colour", + choices = colours1, + selected = "black", + multiple = F, + width = "200px" + ) + + + ), # end text + + tabPanel( + title = "Canvas", + br(), + + sliderInput( + inputId = "plot_width", + label = "Plot width (pixels)", + value = 600, + min = 500, + step = 100, + max = 1500 + ), + + sliderInput( + inputId = "plot_height", + label = "Plot height (pixels)", + value = 600, + min = 500, + step = 100, + max = 1500 + ) + + ), # end canvas + + + + tabPanel( + title = "Pdf", + br(), + + sliderInput( + inputId = "plot_width_cm", + label = "Pdf plot widht (cm)", + value = 12, + min = 10, + step = 1, + max = 20 + ), + + sliderInput( + inputId = "plot_height_cm", + label = "Pdf plot height (cm)", + value = 12, + min = 10, + step = 1, + max = 20 + ), + + br(), + + downloadButton("download_plot", "Save plot as pdf") + + ), # end pdf + + tabPanel( + title = "Layout", + br(), + + # selectizeInput( + # inputId = "layout_method", + # label = "Igraph layout algorithm", + # choices = igraph_layout_algos, + # selected = "layout_nicely", + # multiple = F, + # width = "200px" + # ), + + + br(), + + # fileInput( + # inputId = "matrix_infile", + # label = "Upload feature matrix" + # ), + + br(), + + actionButton("recalc_layout", "Recalculate layout") + + ) # end layout + + ) + + + + ), + mainPanel( + br(), + + uiOutput("main_header"), + + br(), + uiOutput("bipartite_plot_wrapper"), + + br(), + + tableOutput("plot_click") + + ) + ) + + + ) + + +server <- function(input, output, session) { + + my_plot <- reactiveValues() + + my_data <- readRDS("data20.RDS") + + + output$select_cluster <- renderUI({ + + req(my_data) + + ch <- names(my_data) + + nm <- sprintf("%s (%s)", ch, map_int(my_data, ~nrow(.x$node))) + map_int(my_data, ~nrow(.x$node)) + + selectizeInput( + inputId = "cluster", + label = "Choose cluster", + choices = ch %>% set_names(nm), + selected = ch[1], + multiple = F, + width = "200px" + ) + + }) + + observeEvent( + input$cluster, + { + my_plot$data <- my_data[[input$cluster]] + } + ) + + output$bipartite_plot_wrapper <- renderUI({ + + plotOutput( + "bipartite_plot", + click = "plot_click", + dblclick ="plot_dbl_click", + hover = "plot_hover", + brush = "plot_brush", + height = ifelse(is.null(input$plot_height), 600, input$plot_height), + width = ifelse(is.null(input$plot_width), 600, input$plot_width) + ) + }) + + + + + output$bipartite_plot <- renderPlot({ + + req(my_plot$data) + + my_plot$gg <- + gg_network_plotter( + my_plot$data, + node_size1 = input$node_size1, + node_colour_var = input$node_colour_var, + show_text = input$show_text == "yes", + text_colour_var = input$text_var, + text_size = input$text_size, + text_colour = input$text_colour, + edge_colour_var = input$edge_colour_var, + edge_size = input$edge_size + ) + + my_plot$gg + + }) + + output$plot_click <- renderTable({ + + req(input$plot_click) + + nearPoints( + my_plot$data$node, + input$plot_click, + maxpoints = 1, + threshold = 300 + ) + }) + + # observeEvent( + # input$plot_dbl_click, + # { + # my_plot$highlight_nodes <- NA + # }) + + output$plot_hover <- renderTable({ + + req(input$plot_hover) + + nearPoints( + my_plot$data$node, + input$plot_hover, + maxpoints = 1, + threshold = 100 + ) + + }) + + output$download_plot <- downloadHandler( + + filename = "fbf_bipartite_plot.pdf", + content = function(file) { + ggsave(file, height = input$plot_height_cm, width = input$plot_width_cm, units = "cm") + } + ) + + + onStop(function() { + + env = parent.env(environment()) + + ls(envir = env) %>% + ## .. excluding e.g. session" and "output" + setdiff(c("session", "output", "my_pref_update")) %>% + ## object in a list + mget(envir = env) %>% + ## keep only reactive values + subset(., subset = sapply(., is.reactivevalues)) %>% + ## convert reactive values + sapply(function(z) isolate(reactiveValuesToList(z)), simplify=F) %>% + ## assign to global environment + list2env(envir = .GlobalEnv) + + + cat("Session stopped\n") + cat("Type `save(list=ls(), file='tmp.RData')` to save state variables in your current working directory\n") + cat("Find out what current working directory by typing `getwd()`\n") + }) + + +} + + +shinyApp(ui, server) \ No newline at end of file