Skip to content

Instantly share code, notes, and snippets.

@mikelove
Created April 18, 2016 23:11
Show Gist options
  • Save mikelove/fa1111d54214975f0ff3f477bc000341 to your computer and use it in GitHub Desktop.
Save mikelove/fa1111d54214975f0ff3f477bc000341 to your computer and use it in GitHub Desktop.
---
title: "Package-specific methods"
author: "Mike Love"
date: "April 18, 2016"
output: html_document
---
**Intro**: The Bioconductor project contains analysis
packages which often depend on a number of core packages,
which contain core classes (S4 classes like *eSet*, *SummarizedExperiment*, etc.)
It is recommended not to duplicate the
core classes, but instead to extend these classes
when contributing new packages to the project.
This means that many methods can be applied to a new class
that is defined in a new analysis package.
(This is good! We don't have to re-implement `[` subsetting everytime.)
**Problem:** As far as I can tell there is not an quick and easy way
for users to find out which methods are defined for a
specific class, but restricted to the package that defines the class.
By *quick and easy*, I mean that this should be a few keystrokes,
be easy to remember, and should output a simple character vector.
In Bioconductor, these methods are really the
main ones that a user would be interested in.
These are the important custom accessors
and typical analysis steps.
**Example:** The DESeq2 package has
a main class *DESeqDataSet*, which contains the data, metadata,
and the results that are added through a typical analysis.
```{r}
suppressPackageStartupMessages(library(DESeq2))
dds <- makeExampleDESeqDataSet()
class(dds)
```
The *DESeqDataSet* extends the following classes:
```{r}
extends("DESeqDataSet")
```
So if I want to know, what can I *do* with this `dds` thing,
I can ask:
```{r}
methods(class="DESeqDataSet")
```
But this is a giant list of methods of all the possible things
I can do, not restricted to the methods that the package
author wrote. Of course, both kinds of information are valuable,
but users typically want to know the smaller set.
Martin Morgan pointed me to:
```{r}
showMethods(classes="DESeqDataSet", where=getNamespace("DESeq2"))
```
This is the right information, but is a lot to type,
and in my opinion, too verbose in its output.
I've come up with two messy lines of code, which take a class name
as input and return a simple character vector of the methods:
```{r}
intersect(sapply(strsplit(as.character(methods(class="DESeqDataSet")), ","), `[`, 1), ls(attr(findClass("DESeqDataSet")[[1]],"name")))
```
And another approach:
```{r}
sub("Function: (.*) \\(package .*\\)","\\1",grep("Function",showMethods(classes="DESeqDataSet", where=findClass("DESeqDataSet")[[1]], printTo=FALSE), value=TRUE))
```
Maybe there is an even better way? I'm considering to
define this function and put it into
[rafalib](https://cran.r-project.org/web/packages/rafalib/index.html)
where we have some other convenience functions stashed.
If you have feedback, you can reply to me
<a href="https://twitter.com/mikelove" target="blank">@mikelove</a>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment