cjerzak commited on
Commit
5ec17fb
·
verified ·
1 Parent(s): b44c654

Update app.R

Browse files
Files changed (1) hide show
  1. app.R +145 -42
app.R CHANGED
@@ -1,58 +1,161 @@
 
 
 
1
  library(shiny)
 
 
2
  library(bslib)
3
- library(dplyr)
4
- library(ggplot2)
5
 
6
- df <- readr::read_csv("penguins.csv")
7
- # Find subset of columns that are suitable for scatter plot
8
- df_num <- df |> select(where(is.numeric), -Year)
9
 
 
10
  ui <- page_sidebar(
11
- theme = bs_theme(bootswatch = "minty"),
12
- title = "Penguins explorer",
13
  sidebar = sidebar(
14
- varSelectInput("xvar", "X variable", df_num, selected = "Bill Length (mm)"),
15
- varSelectInput("yvar", "Y variable", df_num, selected = "Bill Depth (mm)"),
16
- checkboxGroupInput("species", "Filter by species",
17
- choices = unique(df$Species), selected = unique(df$Species)
 
 
 
 
 
18
  ),
19
- hr(), # Add a horizontal rule
20
- checkboxInput("by_species", "Show species", TRUE),
21
- checkboxInput("show_margins", "Show marginal plots", TRUE),
22
- checkboxInput("smooth", "Add smoother"),
 
 
23
  ),
24
- plotOutput("scatter")
 
 
 
 
 
25
  )
26
 
 
27
  server <- function(input, output, session) {
28
- subsetted <- reactive({
29
- req(input$species)
30
- df |> filter(Species %in% input$species)
 
 
 
 
 
 
31
  })
32
-
33
- output$scatter <- renderPlot(
34
- {
35
- p <- ggplot(subsetted(), aes(!!input$xvar, !!input$yvar)) +
36
- theme_light() +
37
- list(
38
- theme(legend.position = "bottom"),
39
- if (input$by_species) aes(color = Species),
40
- geom_point(),
41
- if (input$smooth) geom_smooth()
42
- )
43
-
44
- if (input$show_margins) {
45
- margin_type <- if (input$by_species) "density" else "histogram"
46
- p <- p |> ggExtra::ggMarginal(
47
- type = margin_type, margins = "both",
48
- size = 8, groupColour = input$by_species, groupFill = input$by_species
49
- )
50
  }
51
-
52
- p
53
- },
54
- res = 100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  )
 
 
 
 
 
 
 
 
56
  }
57
 
58
- shinyApp(ui, server)
 
 
1
+ # app.R: Shiny App for Generating Organizational Embeddings using LinkOrgs
2
+
3
+ # Required libraries
4
  library(shiny)
5
+ library(LinkOrgs)
6
+ library(DT)
7
  library(bslib)
8
+ library(shinyWidgets)
 
9
 
10
+ # Startup code
11
+ options(shiny.maxRequestSize = 30 * 1024^2)
 
12
 
13
+ # UI definition
14
  ui <- page_sidebar(
15
+ theme = bs_theme(bootswatch = "flatly"),
16
+ title = "OrgEmbed: Generate Organizational Embeddings",
17
  sidebar = sidebar(
18
+ radioButtons("input_mode", "Input Method:", choices = c("CSV Upload" = "csv", "Paste Text" = "text")),
19
+ conditionalPanel(
20
+ condition = "input.input_mode == 'csv'",
21
+ fileInput("file", "Upload CSV", accept = ".csv"),
22
+ selectInput("col_select", "Names Column:", choices = NULL)
23
+ ),
24
+ conditionalPanel(
25
+ condition = "input.input_mode == 'text'",
26
+ textAreaInput("text_names", "Paste Names (one per line)", rows = 5)
27
  ),
28
+ numericInput("max_rows", "Max Rows to Process", value = 5000, min = 1),
29
+ selectInput("ml_version", "ML Version:", choices = c("v1", "v2", "v3", "v4"), selected = "v4"),
30
+ checkboxInput("include_original", "Include Original Names in Output", value = TRUE),
31
+ actionButton("process", "Generate Embeddings", class = "btn-primary"),
32
+ bs_tooltip(id = "text_names", title = "Names should be one per row, e.g., 'Apple Inc.'"),
33
+ actionButton("help_btn", "Help")
34
  ),
35
+ mainPanel(
36
+ DTOutput("preview"),
37
+ uiOutput("summary_card"),
38
+ downloadButton("download", "Download Embeddings CSV", class = "btn-success"),
39
+ uiOutput("progress_ui")
40
+ )
41
  )
42
 
43
+ # Server logic
44
  server <- function(input, output, session) {
45
+
46
+ # On startup, initialize backend
47
+ observe({
48
+ tryCatch({
49
+ BuildBackend(conda = "auto")
50
+ showNotification("Backend initialized successfully.")
51
+ }, error = function(e) {
52
+ showNotification("Backend setup failed—check internet or conda path.", type = "error")
53
+ })
54
  })
55
+
56
+ # Reactive: Parse user input
57
+ input_df <- reactive({
58
+ req(input$process)
59
+ if (input$input_mode == "csv") {
60
+ req(input$file)
61
+ df <- read.csv(input$file$datapath, stringsAsFactors = FALSE)
62
+ updateSelectInput(session, "col_select", choices = colnames(df))
63
+ req(input$col_select)
64
+ if (!input$col_select %in% colnames(df) || nrow(df) == 0) {
65
+ showNotification("Invalid names column—please select again.", type = "error")
66
+ return(NULL)
 
 
 
 
 
 
67
  }
68
+ data.frame(names = df[[input$col_select]])
69
+ } else {
70
+ req(input$text_names != "")
71
+ names_list <- trimws(strsplit(input$text_names, "\n")[[1]])
72
+ names_list <- names_list[names_list != ""]
73
+ data.frame(names = names_list)
74
+ }
75
+ })
76
+
77
+ # Preview table
78
+ output$preview <- renderDT({
79
+ req(input_df())
80
+ datatable(head(input_df(), 10), options = list(pageLength = 10))
81
+ })
82
+
83
+ # Reactive: Embeddings result
84
+ embeddings <- reactiveVal(NULL)
85
+
86
+ # Trigger embedding generation
87
+ observeEvent(input$process, {
88
+ df <- input_df()
89
+ if (is.null(df) || nrow(df) == 0) {
90
+ showNotification("Please provide at least one valid name.", type = "error")
91
+ return()
92
+ }
93
+ if (nrow(df) > input$max_rows) {
94
+ showModal(modalDialog("Large dataset detected—processing may take time. Proceed?",
95
+ footer = tagList(modalButton("Cancel"), actionButton("proceed_large", "Proceed"))))
96
+ return()
97
+ }
98
+ process_embeddings()
99
+ })
100
+
101
+ # Handle large input confirmation
102
+ observeEvent(input$proceed_large, {
103
+ removeModal()
104
+ process_embeddings()
105
+ })
106
+
107
+ # Function to process embeddings with progress
108
+ process_embeddings <- function() {
109
+ withProgress(message = "Generating Embeddings", value = 0, {
110
+ incProgress(0.1, detail = "Parsing input...")
111
+ df <- head(input_df(), input$max_rows)
112
+ showNotification(sprintf("Processing %d names...", nrow(df)))
113
+
114
+ incProgress(0.2, detail = "Initializing model...")
115
+ tryCatch({
116
+ rep_x <- LinkOrgs(
117
+ x = df, y = NULL, by.x = "names",
118
+ algorithm = "ml", ml_version = input$ml_version,
119
+ ExportEmbeddingsOnly = TRUE
120
+ )
121
+ embed_df <- rep_x$embedx
122
+ if (!input$include_original) embed_df <- embed_df[, -1]
123
+ embeddings(embed_df)
124
+ incProgress(0.7, detail = "Generating embeddings...")
125
+ }, error = function(e) {
126
+ showNotification(sprintf("Error: %s", e$message), type = "error")
127
+ embeddings(NULL)
128
+ })
129
+ incProgress(1, detail = "Complete!")
130
+ })
131
+ }
132
+
133
+ # Summary card
134
+ output$summary_card <- renderUI({
135
+ req(embeddings())
136
+ card(
137
+ sprintf("Embeddings generated for %d names. Dimensions: %d.",
138
+ nrow(embeddings()), ncol(embeddings()))
139
+ )
140
+ })
141
+
142
+ # Download handler
143
+ output$download <- downloadHandler(
144
+ filename = "org_embeddings.csv",
145
+ content = function(file) {
146
+ req(embeddings())
147
+ write.csv(embeddings(), file, row.names = FALSE)
148
+ }
149
  )
150
+
151
+ # Help modal
152
+ observeEvent(input$help_btn, {
153
+ showModal(modalDialog(
154
+ title = "Usage Guide",
155
+ "1. Upload/paste names.\n2. Click Process.\n3. Download embeddings for use in linkage models."
156
+ ))
157
+ })
158
  }
159
 
160
+ # Run the app
161
+ shinyApp(ui = ui, server = server)