zarathucorp / shiny-electron-template-m1

Template repository for build Standalone R Shiny application with Electron
MIT License
34 stars 38 forks source link

How to install Bioconductor packages? #1

Closed YonghuiDong closed 10 months ago

YonghuiDong commented 1 year ago

Hi Jinhwan Kim,

Thanks a lot for the detailed tutorial.

Do you know how to install Bioconductor packages for the shiny app? Maybe it is better to use remotes or renv to install all the required R packages rather than using automagic ?

Best,

Dong

jhk0530 commented 1 year ago

Sorry for the late reply.

First of all, I have not yet succeeded in including packages from github outside of CRAN (bioconductor is the same).

So I used the functions from the github package in a rather strange way, by declaring them one by one inside.

Since I don't know exactly what automagic does, I might consider using remotes or renv as you mentioned.

I was hoping you could recommend a lightweight example package to practice embedding a package from bioconductor inside.

Thank you.

Kim.

YonghuiDong commented 1 year ago

Dear Jinhwan,

Thanks for your kind help.

Here is one simple shiny app using Bioconductor package ComplexHeatmap to plot Heapmap.

library(shiny)
library(ComplexHeatmap)

ui <- fluidPage(
  titlePanel("ComplexHeatmap Demo"),
  mainPanel(plotOutput("heatmapPlot", height = "800px"))
)

server <- function(input, output) {
  output$heatmapPlot <- renderPlot({
    heatmap(as.matrix(mtcars), show_row_names = TRUE, show_column_names = TRUE)
  })
}

shinyApp(ui = ui, server = server)

In the above example, I used only a single Bioconductor package. However ComplexHeatmap relies on 30 direct dependencies and 126 indirect dependencies. Manually declaring and installing all these dependencies can be a cumbersome and error-prone. It will be great that can be installed automatically in a similar way as making shinyapp docker images.

Screen Shot 2023-06-26 at 15 10 41

Best,

Dong

jhk0530 commented 1 year ago

I'll check and let you know. (may in July~August)

YonghuiDong commented 1 year ago

Hi Jinhwan Kim,

I would like to give you a quick update on the installation of Bioconductor packages.

Currently, I copy the entire libraries from my original shiny project into the r-mac folder. This method allows me to install all the necessary packages, including the Bioconductor packages, without the need to run Rscript add-cran-binary-pkgs.R.

It works very well. The only disadvantage is the inclusion of some unnecessary packages, and the resulting electron app is large. I think this issue can be easily solved with renv.

Best regards,

Dong

jhk0530 commented 1 year ago
스크린샷 2023-07-24 오전 2 36 53

Hi, @YonghuiDong

Based on the code you provided, I installed the bioconductor package and succeeded in running the shiny electron app.

and below is code for installing bioconductor's package and their dependency.

Important Note

I couldn't find a function to provide links to the binary files for the bioconductor packages. so I had to manually paste the links to the binary source files in the documentation for each package. (as links)

# Copyright (c) 2023 Jinhwan Kim

# !/usr/bin/env Rscript

# Script to find dependencies of a pkg list, download binaries and put them
# In the standalone R library.

library(BiocPkgTools)

# get dependent Bioconductor Package

get_bioc_pkgs <- function(biocpkgs = 'ComplexHeatmap'){
  res <- biocpkgs 
  while(length(biocpkgs)>0){
    dep <- unname(unlist(BiocPkgTools::pkgBiocDeps(biocpkgs[1])))
    if(length(dep)>0){
      res <- union(res, dep)
      biocpkgs <- biocpkgs[-1]
      for(i in 1:length(dep)){
        if(!dep[i] %in% biocpkgs){
          biocpkgs <- c(biocpkgs, dep[i]) 
        }
      }
    } else{
      biocpkgs <- biocpkgs[-1]
    }
  }

  return(res)
}

get_cran_pkgs <- function(biocPkgs){
  res <- c()
  for(i in 1:length(biocPkgs)){
    CRANdep <- unname(unlist(BiocPkgTools::pkgBiocDeps(biocPkgs[i], only.bioc = FALSE)))
    bioCdep <- unname(unlist(BiocPkgTools::pkgBiocDeps(biocPkgs[i])))
    res <- union(res, setdiff(CRANdep, bioCdep))
  }
  return(res)
}

# ComplexHeatmap - IRanges - BiocGenerics - S4Vectors 

links <- c('https://bioconductor.org/packages/release/bioc/bin/macosx/big-sur-arm64/contrib/4.3/ComplexHeatmap_2.16.0.tgz',
           'https://bioconductor.org/packages/release/bioc/bin/macosx/big-sur-arm64/contrib/4.3/IRanges_2.34.1.tgz',
           'https://bioconductor.org/packages/release/bioc/bin/macosx/big-sur-arm64/contrib/4.3/BiocGenerics_0.46.0.tgz',
           'https://bioconductor.org/packages/release/bioc/bin/macosx/big-sur-arm64/contrib/4.3/S4Vectors_0.38.1.tgz')

td <- tempdir()
decompress <- untar

# download tgz file to temporary directory

for( i in 1:length(links)){
  downloaded <- download.file(links[i], destfile = paste0(td, '/package.tgz'))  
  decompress(paste0(td, '/package.tgz'), exdir = file.path('r-mac', 'library')) # unzip to r-mac library
  unlink(paste0(td, '/package.tgz')) # delete temporary downloaded file
}

# delete unnecessary files
remove_dirs = c("help", "doc", "tests", "html", "include", "unitTests", file.path("libs", "*dSYM"))

z <- lapply(
  list.dirs(file.path('r-mac', 'library'), full.names = TRUE, recursive = FALSE),
  function(x) {
    unlink(file.path(x, remove_dirs), force = TRUE, recursive = TRUE) # delete
  }
)
invisible(NULL)

############## SAME code to install bioconductor-cran dependent packages
## install cran packages

library(automagic)

options(repos = "https://cloud.r-project.org")

cran_pkgs <- setdiff(unique(c("shiny", automagic::get_dependent_packages("shiny"))), "automagic")
cran_pkgs <- union(cran_pkgs, get_cran_pkgs(biocPkgs))

install_bins <- function(
    cran_pkgs, library_path, type, decompress,
    remove_dirs = c(
      "help", "doc", "tests", "html",
      "include", "unitTests",
      file.path("libs", "*dSYM")
    )) {
  installed <- list.files(library_path) # check installed packages

  cran_to_install <- sort(setdiff(
    unique(unlist(
      c(cran_pkgs,
        tools::package_dependencies(cran_pkgs,
                                    recursive = TRUE,
                                    which = c("Depends", "Imports", "LinkingTo")
        ))
    )),
    installed
  ))

  if (!length(cran_to_install)) {
    message("No packages to install")
  } else {
    td <- tempdir()
    downloaded <- download.packages(cran_to_install, destdir = td, type = type)
    apply(downloaded, 1, function(x) decompress(x[2], exdir = library_path))
    unlink(downloaded[, 2])
  }

  z <- lapply(
    list.dirs(library_path, full.names = TRUE, recursive = FALSE),
    function(x) {
      unlink(file.path(x, remove_dirs), force = TRUE, recursive = TRUE)
    }
  )
  invisible(NULL)
}

if (dir.exists("r-mac")) {
  install_bins(
    cran_pkgs = cran_pkgs, library_path = file.path("r-mac", "library"),
    type = "mac.binary.big-sur-arm64", decompress = untar
  )
}

I checked your comment before (copy and paste all packages) and it may work. and i think it's not elegant way but still fine if it worked.

only you can try is remove unnecessary files for each packages like Doc / Help. and it can be done with below's code

library_path = file.path("r-mac", "library")
  z <- lapply(
    list.dirs(library_path, full.names = TRUE, recursive = FALSE),
    function(x) {
      unlink(file.path(x, remove_dirs), force = TRUE, recursive = TRUE)
    }
  )
  invisible(NULL)

and finally

This is bad news.

Although I verified execution with electron-forge start command,

the creating the standalone app with electron-forge make was not possible due to an unknown error.

after I checked error log some font-config file in R (4.3.1 version) made this issue.

so I removed every file in r-mac/fontconfig/fonts/conf.d directory and it built (but not run)

but I think you may solve your main problem: Install bioconductor packages.

Thanks.

Kim

YonghuiDong commented 1 year ago

Dear Kim,

Thanks a lot for your help. I will test it and update you soon.

Best regards,

Dong

jhk0530 commented 10 months ago

I closed this issue, but if problem occurs again, you're welcome to re-open or create new issue.