Skip to content

[Bioc-devel] Recent issue with plot method dispatch

5 messages · Joern Toedling, Martin Morgan

#
Hello,

I have encountered a strange issue with the plotting function in my 
package "girafe" that I need some help with. I haven't changed anything 
in the plot methods or the NAMESPACE of the package recently, and it 
worked before, yet I observe the following error now.

When calling the "plot" method for objects of the class 
"AlignedGenomeIntervals", rather than using the appropriate S4 method 
and calling another function (plotAligned), R falls back to the S3 
method "plot.Intervals_full" (Intervals_full is the class that 
AlignedGenomeIntervals indirectly inherits from). Please see below for 
the sessionInfo() output.

Has anybody encountered the same behaviour or any insights what might be 
going on? I'm grateful for any suggestions what I could fix in the 
method definition and/or the NAMESPACE. I guess as a workaround I could 
add an S3 plot method for the "AlignedGenomeIntervals" calls but that 
would be rather ugly.

Thanks in advance,
Joern


 > sessionInfo()
R Under development (unstable) (2013-03-12 r62224)
Platform: x86_64-unknown-linux-gnu (64-bit)
...
other attached packages:
  [1] org.Mm.eg.db_2.9.0     RSQLite_0.11.2 DBI_0.2-5
  [4] AnnotationDbi_1.21.13  Biobase_2.19.3 girafe_1.11.2
  [7] genomeIntervals_1.15.1 intervals_0.14.0 ShortRead_1.17.10
[10] latticeExtra_0.6-24    RColorBrewer_1.0-5 lattice_0.20-13
[13] Rsamtools_1.11.21      Biostrings_2.27.11 GenomicRanges_1.11.36
[16] IRanges_1.17.37        BiocGenerics_0.5.6 BiocInstaller_1.9.7

loaded via a namespace (and not attached):
[1] bitops_1.0-5    BSgenome_1.27.1 hwriter_1.3     stats4_3.1.0
[5] tcltk_3.1.0     tools_3.1.0     zlibbioc_1.5.0


Example producing the error:

library("girafe")
example("plotAligned")
#
On 03/13/2013 04:02 AM, Joern Toedling wrote:
I think this is a bug in S4, triggered by complex relations between the 
intervals and girafe package. I'll pursue this on R-devel.

I can reproduce this with a PkgA that has DESCRIPTION with

Depends: intervals
Imports: graphics

NAMESPACE:

importFrom(graphics, "plot")
export("plot")
exportMethods("plot")

R/tmp.R

setClass("A")
setMethod("plot", "A", function(x, y, ...) {})


and then

 > library(PkgA)
Loading required package: intervals
 > plot
function (x, y, ...)
UseMethod("plot")
<environment: namespace:graphics>

notice that 'plot' is reported as an S3 generic, but should be an S4 generic.

Removing Depends: intervals or changing to importsFrom(intervals, "plot") 
recovers S4 export

 > library(PkgA)
Loading required package: intervals
 > plot
standardGeneric for "plot" defined from package "graphics"

function (x, y, ...)
standardGeneric("plot")
<environment: 0x60aea90>
Methods may be defined for arguments: x, y
Use  showMethods("plot")  for currently available ones.


The 'intervals' package Depends: on methods but nothing else. It defines S3 and 
S4 methods on plot, creating an implicit S4 generic in the process. It's 
NAMESPACE has

S3method( "plot", "Intervals" )
S3method( "plot", "Intervals_full" )
exportMethods("plot")

and we have

 > library(intervals)
 > plot
standardGeneric for "plot" defined from package "graphics"

function (x, y, ...)
standardGeneric("plot")
<environment: 0x68cdc78>
Methods may be defined for arguments: x, y
Use  showMethods("plot")  for currently available ones.

  
    
#
On 03/13/2013 12:32 PM, Martin Morgan wrote:
Actually, from

?Methods

in the section 'Methods for S3 Generic Functions' the recommendation is to do 
just this -- define both an S3 and S4 methods. It is not too ugly

   plot.AlignedGenomeIntervals = function(x, ...) { ... }
   setMethod(plot, "AlignedGenomeIntervals", plot.AlignedGenomeIntervals)

and

   S3method(plot, A)
   exportMethods(plot)

in NAMESPACE. This 'works' in my toy package, though I'd be hard-pressed to 
explain why.

Martin

  
    
#
Hello,

thanks for following up on this, Martin. Indeed the problem was the 
missing S4 generic for "plot" was the problem. For some reason, the most 
recent version of R requires to declare this explicitly or to import the 
generic "plot" from another package. While before, I think that such a 
generic was created automatically when one defined a "plot" method for a 
S4 class.

The previous example:
library("girafe")
example(plotAligned)

actually works if you add a 'setGeneric("plot")' before calling 
'example(plotAligned)'.

I have added this to the development version of 'girafe'. It's 
unfortunate that such changes to R can also break the release version 
but since the release package is there from previous build versions and 
the next release will be soon, it's probably not worth to make any major 
efforts there.

Cheers,
Joern
On 03/13/2013 08:32 PM, Martin Morgan wrote:
3 days later
#
On 03/14/2013 07:16 AM, Joern Toedling wrote:
Hi Joern --

I did follow up with this on R-devel

   https://stat.ethz.ch/pipermail/r-devel/2013-March/066111.html

A change in 'intervals' triggered this problem (exporting an S4 method and hence 
generic for plot), not a change in R.

The problem was that setMethod finds the S4 generic 'plot' on the search path, 
rather than the S3 plot imported in your  name space (I personally think this is 
not correct behaviour); your namespace then exports the unmodified S3 generic, 
masking the S4 generic on the search path that your method was added to.

A better work-around is to importFrom(intervals, plot); this avoids creating 
another S4 generic 'plot'. Experience has shown that having multiple generics of 
the same function creates problems as additional packages enter the picture; 
this is what motivates the BiocGenerics package.

An additional enhancement, not under your control, would be for intervals to 
reuse the S4 plot generic from stats4 -- importFrom (stats4, plot) -- and for 
your package too to importFrom(stats4, plot); the packages would then be adding 
methods to the same generic, and could do so independently of what packages 
(other than stats4) were doing.

Martin