3 min read

miniCRAN

Next month, I’m teaching a workshop on R/qtl and R/qtl2 at the joint Complex Trait Community and Rat Genomics Community meeting (CTC-RG2017) meeting in Memphis.

I was chatting with Śaunak Sen about preparations: the main problem is installation of R/qtl2, which is split into multiple R packages, and I’ve not yet placed them on CRAN. And they’re a bit of a pain to install from GitHub (people need the proper development tools, and compilation of the C++ code is painfully slow).

Should we have participants work on a server? Should we set up RStudio in Docker containers on Digital Ocean?

Śaunak said, “What we need is a mini-CRAN.” A google search brought us to the package miniCRAN from Revolution Analytics, which looks to be the perfect solution.

As it turns out, to make your own CRAN you “just” need to put all of the requisite packages (source plus windows and mac binaries) into a specific directory structure, with each directory having special files (PACKAGE, PACKAGE.gz, and PACKAGE.rds) that describe the contents.

The main trick is ensuring that you have all of the required dependencies, and that’s where miniCRAN is especially helpful.

miniCRAN has several useful vignettes, plus a nice blog post that explains the goal and basic use.

After installing miniCRAN, the first thing was to define the set of packages that my R/qtl2 packages depend on, and then use miniCRAN::pkgDep to find all of the packages that those depend on.

library(miniCRAN)
repo <- "https://cran.rstudio.com"
pkgs <- c("Rcpp", "RcppEigen", "yaml", "jsonlite", "data.table",
          "knitr", "rmarkdown", "qtl", "qtlcharts")
pkgList <- pkgDep(pkgs, repos=repo, type="source", suggests=FALSE)

Here pkgs is a vector containing the main packages that we’ll need (other than the R/qtl2 packages), and pkgList is a longer vector that includes all packages that they depend on.

We then use miniCRAN::makeRepo to download all of those packages and place them in the required directory structure, with the main directory being qtl2cran:

makeRepo(pkgList, path="qtl2cran", repos=repo,
         type=c("source", "win.binary", "mac.binary.el-capitan"))

The only issue here is that the version of miniCRAN on CRAN doesn’t handle mac.binary.el-capitan properly, nor does the version on GitHub. But there’s a pull request from Vincent Nijs that fixes that, so I used devtools::install_github("vnijs/miniCRAN") to use his version.

I then needed to add my R/qtl2 packages:

  • source .tar.gz files in qtl2cran/src/contrib
  • Windows .zip files in qtl2cran/bin/windows/contrib/3.4
  • Mac .tgz files in qtl2cran/bin/macosx/el-capitan/contrib/3.4

I’m working on a Mac (with OS X Sierra) so I could create the Mac binaries by installing the packages, going to the package directory, and using for example

tar czvf qtl2geno_0.5-21.tgz qtl2geno

For the windows binaries, I untarred the source files on my windows laptop and used, for example:

R CMD INSTALL --build qtl2geno

This makes the qtl2geno_0.5-21.zip file.

The last step is to create those PACKAGE* files. A bit of poking around in the miniCRAN source pointed me to tools::write_PACKAGES(), and so I used:

library(tools)
write_PACKAGES("qtl2cran/src/contrib", type="source")
write_PACKAGES("qtl2cran/bin/windows/contrib/3.4", type="win.binary")
write_PACKAGES("qtl2cran/bin/macosx/el-capitan/contrib/3.4",
               type="mac.binary")

I then put them on my website at UW-Madison plus at rqtl.org, so now people can install R/qtl2 using either

install.packages(paste0("qtl2", c("geno", "scan", "plot", "convert")),
                 repos="https://rqtl.org/qtl2cran")

or

install.packages(paste0("qtl2", c("geno", "scan", "plot", "convert")),
                 repos="https://www.biostat.wisc.edu/~kbroman/qtl2cran")

We just need to make sure that everyone has R version 3.4.0. And the Mac users will need a relatively recent version of Mac OS X (El Capitan or Sierra).

Long term, I need to get my packages on the proper CRAN, but I really don’t want to have to deal with that in the next three weeks, and so I’m glad for miniCRAN, as it helped me towards this short-term solution.