-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.Rmd
More file actions
202 lines (150 loc) · 9.39 KB
/
Copy pathindex.Rmd
File metadata and controls
202 lines (150 loc) · 9.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
---
title: "Developing Bioconductor-friendly packages using biocthis"
author:
- name: "David Zhang"
affiliation: UCL
date: "`r format(Sys.time(), '%d %B %Y')`"
output:
html_document:
df_print: kable
keep_md: true
---
```{r setup, include = FALSE}
library(knitr)
library(tidyverse)
knitr::opts_chunk$set(echo = FALSE, message = FALSE)
```
> Note: install the development version of biocthis via `devtools::install_github("lcolladotor/biocthis")` and any additional dependencies.
# Outline
1. Why make R/Bioconductor packages?
2. What do R packages consist of?
3. Testing fundamentals.
4. Package development packages - `usethis`, `devtools` and `biocthis`.
5. Package development workflow.
6. Additional resources.
7. Making your own Bioconductor-friendly package.
# Why make R/Bioconductor packages?
## R packages
- **Share** functions with others/yourself.
- Improving the **organization** of your functions - e.g. mentality, documentation, continuous updates.
- Integrated **unit testing** to keep your functions robust to future changes.
Useful resources:
1. R packages [book](https://rstudio.com/products/rpackages/)
2. [Your first R package in 1 hour](https://www.pipinghotdata.com/posts/2020-10-25-your-first-r-package-in-1-hour/)
## Bioconductor packages
- **Share** code more widely with Bioconductor community.
- Code review, learning about developing software - forced compliance with Bioconductor standards.
- [More citations](https://www.biorxiv.org/content/10.1101/2020.11.16.385211v1)
- CV/reputation points.
# What do R packages consist of?
## States of R packages
- The states of R packages is explained well [here](https://r-pkgs.org/package-structure-state.html).
- 5 states:
1. **source** - A set files/directories in a set structure. The state you develop with and encounter when cloning a GitHub repository.
2. **bundles** - Source compressed into a single tar.gz (e.g. through `devtools::build()`)
3. **binary** - Binary version (e.g. distributed by CRAN). Can be generated through `devtools::build(binary = TRUE)`.
4. **installed** - Either the binary or bundle that's decompressed and placed into your R package library (using `install.packages()`)
5. **in-memory** - Load a package into memory using `library()` or `devtools::load_all()`.
## Structure of R packages
R packages have several key components, which are shown in screen-shot taken from [the biocthis GitHub repository](https://github.com/lcolladotor/biocthis) below:
```{r key-components}
knitr::include_graphics("figures/biocthis_package_structure.png")
```
1. **.github** - GitHub actions workflow.
2. **R** - Contains all the code for the functions of your package.
3. **dev** - Package development helper scripts from `biocthis`.
4. **inst** - Additional raw data you would like available to the user.
5. **man** - Function documentation generated by Roxygen.
6. **tests** - Unit tests for functions.
7. **vignettes** - Vignette description usage of your package
8. **DESCRIPTION** - Author details, license, dependencies and general summary of your package.
9. **README.md** - Documentation shown at the GitHub repository.
10. **NEWs.md** - Collection of updates for package for users to scan through.
# Testing fundamentals
3 levels of testing:
1. **Unit testing** individual functions.
2. **R CMD Check or BiocCheck** checks that you're package can be built, installed and complies to R/Bioconductor package guidelines.
3. Testing across multiple **operating systems** using GHA.
## Unit testing
- For complicated code, ensures future updates do not break existing functionality.
- You do this already, just manually.
- `testhat` automates this for R packages.
- Rule of thumb: If you catch a bug, write a test.
- Metrics, try to be fast + comprehensive.
## R CMD Check or BiocCheck
- `R CMD Check` that your package meets certain criteria:
- Runs all unit tests
- Have you set all the dependencies you need?
- Have you documented your functions?
- Have you written a proper `DESCRIPTION`?
- Have you used `:::`?
- Lots more... see [R packages page on R CMD Check](https://r-pkgs.org/r-cmd-check.html)
- `BiocCheck` is more stringent:
- Are your functions less than 80 lines?
- Do >80% have examples?
- Reports `ERROR`/`WARNING`/`NOTE`s.
## Testing across Linux/Mac/Windows
- A great lecture on GHA basics from Jim Hester can be found [here](https://www.jimhester.com/talk/2020-rsc-github-actions/).
- GitHub actions is used in this case for testing, but is very flexible.
- On an event, do something.
- Written in yet-another-markdown-language (YAML).
- GitHub has "runners" based on Linux/Mac/Windows OS (and permits dockers).
- We run `R CMD Check` and `BiocCheck` on all 3 to check for OS-specific issues.
# Package development packages
`usethis`, `devtools` and `biocthis` are convenient helper packages for developing R/bioconductor packages respectively.
## usethis
- [usethis](https://usethis.r-lib.org/) has a lot of functions to enable easy package development.
- `usethis::create_package()` - creates package skeleton.
- `usethis::use_r()` - creates .R function skeleton.
- `usethis::use_test()` - create test skeleton.
- `usethis::use_package()` - add a dependency to `Imports`.
- `usethis::use_git()` - connects current package to git.
- `usethis::use_github()` - create a GitHub repo for current repo.
- `usethis::use_github_action()` - creates GHA skeleton.
## devtools
- [devtools](https://www.r-project.org/nosvn/pandoc/devtools.html) is aimed at "making your life as a package developer easier"
- `devtools::load_all()` - load your current package
- `devtools::test()` - run all unit tests
- `devtools::check()` - run `R CMD Check`
- `devtools::document()` - document with [roxygen2](https://cran.r-project.org/web/packages/roxygen2/vignettes/roxygen2.html)
- `devtools::build()` - build your current package
- `devtools::install()` - installs your current package
## biocthis
- [biocthis](https://github.com/lcolladotor/biocthis) extends `usethis` specifically for Bioconductor packages:
- Templates for creating `DESCRIPTION`, `README.md` and vignettes
- Styles using `BiocStyle`
- Sets up a GitHub action workflow on all 3 OS (including using the Bioconductor docker for Linux) that includes `R CMD Check` and `BiocCheck`.
- Deploys a `pkgdown` page for your package.
- Sets up code coverage check.
- Still under active development.
# Package development workflow
A top-level workflow for modifying your package, then running tests and updating via `git` is shown below.
```{r package-dev-workflow, out.height = 1000, fig.align = 'center'}
knitr::include_graphics("https://lucid.app/publicSegments/view/22dc40f9-49b9-47ef-b04c-9fae764bf492/image.png")
```
# Additional resources
- What makes good tests/documentation? Where should I put raw vs processed vs internal data? What else does `R CMD Check` check? The [R packages](https://r-pkgs.org/r-cmd-check.html) book is highly recommended.
- Writing `R` functions - good practices can be found in the [tidyverse design guide](https://design.tidyverse.org/structure.html).
- `testthat` - [3rd edition](https://rstudio.com/resources/webinars/testthat-3/)
- How to write your own GHA workflow? A good place to start with using GHA in R can be found [here](https://ropenscilabs.github.io/actions_sandbox/).
- Submission/maintenance of Bioconductor packages. Info regarding submissions can be found [here](https://www.bioconductor.org/developers/package-submission/) and maintaining packages [here](https://www.bioconductor.org/developers/how-to/git/).
- An alternative making Bioconductor packages workshop can be found [here](https://saskiafreytag.github.io/making_bioconductor_pkg/articles/workshop.html). This covers in detail additional topics such as submitting your package to Bioconductor.
# Making your own Bioconductor-friendly package
1. Create an R package skeleton with `usethis::create_package("path_to_package")`.
2. Create `dev/` folder with `biocthis` scripts using `biocthis::use_bioc_pkg_templates()`.
3. Run `available::available("package_name")` to check package name availability.
4. Run through `dev/02_git_github_setup.R` (adding GitHub PAT and ssh keys if not set up already). Check your initial skeleton has been pushed to GitHub repo.
5. Finishing setting up `dev/03_core_files.R`. You may need to install `knitcitations` from GitHub with `remotes::install_github("cboettig/knitcitations")`. You may also need to install your package via `devtools::install(".")` before running `pkgdown::deploy_to_branch()`.
6. `usethis::use_r("function_name")` - add your own function with documentation and dependencies via `usethis::use_package("package_name")`: example function [get_sum_stats.R](https://github.com/dzhang32/rutils/blob/master/R/get_sum_stats.R).
7. `usethis::use_test("function_name")` - add testing for your function: example tests [test-get_sum_stats.R](https://github.com/dzhang32/rutils/blob/master/tests/testthat/test-get_sum_stats.R).
8. Run unit tests via `devtools::test()`.
9. Run `04_update.R` to auto-style and document your code.
10. Run R CMD Check via `devtools::check()`.
11. If passed then push your changes to GitHub. Review `ERROR`/`WARNING`/`NOTES` then make any necessary changes (e.g. more `biocViews`) and update.
# Reproducibility
```{r reproducibility, echo = FALSE}
# Session info
library("sessioninfo")
options(width = 120)
session_info()
```