2  Kickstarting an R package

Aims
  • Kickstart an R package
  • Write functions
  • Document functions
Tip

At any time, if you are lost or do not understand how functions in the proposed solution work, type ?<function> in the R console and a help menu will appear.

You can also check the help tab in the corresponding quadrant.

2.1 Proposed package functionalities

In this section, we are going to create a package which aims at:

  1. Importing .bigwig coverage track files as well as .bed files of genomic coordinates
  2. Filtering imported GRanges to make sure they all are contained within the coverage tracks
  3. Calculating the average (+/- quantiles) of coverage of the .bigwig file over the GRanges of interest
  4. Plot the aggregated .bigwig coverage over the GRanges of interest

Eventually, the functions shipped in this package should be able to turn a pair of .bigwig/.bed files into this type of plot:

2.2 Starting a new package

To start developing a new package, one may want to make sure all useful developer resources are already set-up.

Question

Make sure to install the developer toolkit packages.

install.packages("remotes")
remotes::install_cran(
    c(
        "available",
        "devtools",
        "rcmdcheck", 
        "knitr",
        "pkgdown",
        "RefManageR",
        "rmarkdown",
        "rstudioapi",
        "sessioninfo",
        "styler",
        "usethis",
        "gert"
    )
)
remotes::install_cran("BiocManager")
BiocManager::install(c("BiocStyle", "BiocCheck", "biocthis"))

Now the time has come to create your very first package! To keep a coherent cohorte, we’ll create a package named <YOURNAME>TestPackage. But first, you need to make sure that this package name is available.

Question

Verify that your package name is available, with the available package.

available::available("JacquesTestPackage")

If this name is available, let’s create your package.

Question

Which function from devtools can be used to create a package skeleton? Use it to create your package.

library(devtools)
setwd("~")
create_package("JacquesTestPackage")

When creating your package, devtools+RStudio combo automatically opens a new RStudio window, with the package’s project automatically activated. Navigate to your package RStudio project window and re-open this instruction sheet.

Question

Make sure you’re in the right project using the appropriate function from rstudioapi package.

usethis::proj_activate("~/JacquesTestPackage/")
rstudioapi::getActiveProject()
Question

Explore the newly created folder architecture. Do you recognize all the files and directories?

The DESCRIPTION file automatically created does not exactly match Bioconductor requirements. You should replace it by a better-fitted DESCRIPTION file.

Question

Find the appropriate function from biocthis to replace the current DESCRIPTION file by one fitting BIOCONDUCTOR’s requirements.

biocthis::use_bioc_description()
Question

Manually edit the important fields from your new DESCRIPTION file: Title & Author. The remaining fields will be filled out later on.

Question

Now add a LICENSE file to specify under which license you wish to publish your package.

usethis::use_mit_license()

A nice touch is to systematically provide a README file. This provides a good overview of your package when browsed e.g. in GitHub, and for non-R specialists, who don’t necessarily know about DESCRIPTION and vignettes. And since you are developing an R package, let’s stick with the Rmd format for your README.

Question

What are the benefits of having a README.Rmd file?

Which function from biocthis can create a .Rmd README file?

biocthis::use_bioc_readme_rmd()

That being said, package submission requires that a REAMDE.md file only is present in the repository. A way to provide this is to 1) devtools::build_readme() to parse README.Rmd into README.md (with R chunks processed!), and 2) add README.Rmd to .gitignore.

Question

Parse your README.Rmd into README.md and check the differences.

devtools::load_all('.')
devtools::build_readme()
rstudioapi::documentOpen("README.Rmd")
rstudioapi::documentOpen("README.md")

A bunch of extra useful commands from bioc/usethis can be performed at this stage, e.g. to add a NEWS file, a Code of Conduct, a citation file, etc… Beware, each command creates/modify one/several files. Pay attention to the comments printed in the R console!

Question

Run each of the following commands one by one and make sure to fulfill each required action highlighted in the R console.

biocthis::use_bioc_news_md()  ## To add a NEWS.md file
biocthis::use_bioc_coc()  ## To add a .github/CODE_OF_CONDUCT.md file
biocthis::use_bioc_support()  ## To add a .github/SUPPORT.md file
biocthis::use_bioc_issue_template()  ## To add a .github/ISSUE_TEMPLATE/issue_template.md file
biocthis::use_bioc_citation()  ## To add a inst/CITATION file
usethis::use_lifecycle_badge("Experimental")  ## To add a "Experimental" badge to your README.Rmd
devtools::build_readme()  ## To rebuild README.md

2.3 Write functions to populate your package

To write your first package function, you can either create an R/<name>.R file manually, or run usethis::use_r(name).

Now is time to write! Refer to the functionalities (descriped in Section 0) that we are aiming to provide in this package, and start writing 4 functions which, together, can fulfill these functionalities. Briefly, we suggest to design functions to:

  1. import a coverage track and a set of genomic features (scaled to a fixed width) together in a list;
  2. filter the imported features to only retain those fully overlapping with covered genome segments (from the coverage track);
  3. compute the mean coverage and its confidence interval, for each position within the features’ width;
  4. plot the results with ggplot2.
Tip

These functions should work in a chain:

import(bw_path, features_path, width) |>
    filter() |> 
    compute() |> 
    plot()
Tip

The content of the proposed function files is shown in Share/Day2/functions/. These files provides an example of implementation to fulfill our package’s requirements.

2.4 Add function documentation

Question

Write oxygen tags (title, description, @param, @return, …) for each function.

Once you have documented each function, you can regenerate the documentation with document().

document()