[BioC] On extending class ExpressionSet
Renaud Gaujoux
renaud at mancala.cbio.uct.ac.za
Thu Dec 16 07:05:21 CET 2010
Hi Morgan,
thank you very much for the explanation on the initialize method for the
class ExpressionSet.
I always found the S4 initialization mechanism a bit difficult to handle
in the case of inheritance. It often requires to manually pass slots to
the parent class, which should be automatic: each class -- developer --
has to deal only with its own data members.
Maybe I am too optimistic, but would something like the following
definition of initialize,ExpressionSet-method fix the problem without
changing the current behaviour for the dependent packages (since I
assume they all pass assayData as a first argument):
structure(function (.Object, ...)
{
# check if the first argument is an ExpressionSet
# if so: initialize the object with it and tells .local not to
# overwrite slots corresponding to missing arguments.
# otherwise: s
overwrite.missing<- TRUE
dotargs<- list(...)
if( length(dotargs)> 1&& is(dotargs[[1]], 'ExpressionSet') ){
.Object<- dotargs[[1]]
overwrite.missing<- FALSE
dotargs<- dotargs[-1]
}
# .local should initialize (i.e. overwrite) a slot of .Object with its prototype only if overwrite.missing=TRUE, or in any case with the corresponding non missing argument for this slot.
.local<- function (.Object, overwrite.missing=TRUE, assayData, phenoData, featureData,
exprs = new("matrix"), ...)
{
if (overwrite.missing&& missing(assayData)) {
# stuff ...
}
# other stuff ...
}
# call .local with overwrite.missing as its first argument
do.call(.local, c(list(.Object, overwrite.missing), dotargs))
}
I think this would allow:
eset<- new('ExpressionSet', exprs=matrix(0,10,5))
new('ExpressionSet', eset) # simple copy constructor
new('ExpressionSet', eset, exprs=matrix(0,20,3)) # overwrite original exprs with the one given in argument
# etc... with other slots
# and the current behaviour should also work
new('ExpressionSet', assayData=assayData(eset), exprs=matrix(0,10,5))
# and initialize will still set the object to its prototype if directly called (which a behaviour one might not want to change as it could be use by other packages)
initialize(eset)
Thank you.
Renaud
On 15/12/2010 20:21, Martin Morgan wrote:
> On 12/15/2010 09:42 AM, Renaud Gaujoux wrote:
>> Hi,
>>
>> I am trying to extend class ExpressionSet in a very simple way to add an
>> extra slot.
>> Now suppose I have a valid ExpressionSet object, I want to create an
>> object of class 'A' as follows (this always worked with other S4 classes
>> I defined):
>>
>> library(Biobase)
>> setClass('A', representation(extraslot='list'), contains='ExpressionSet')
>> eset<- new('ExpressionSet')
>> new('A', eset)
>>
>> # this throws the error:
>> Error in function (classes, fdef, mtable) :
>> unable to find an inherited method for function
>> "annotatedDataFrameFrom", for signature "ExpressionSet"
>> #Note: this also does not work with a non-empty ExpressionSet object.
>>
>> Is this normal? Is there a specific way to extend the class ExpressionSet?
>> The classes I found that extend ExpressionSet add an extra element in
>> assayData, and from what I saw it requires defining an initialize method
>> to pass all the standard parameters to the underlying ExpressionSet
>> object (exprs, phenoData, featureData, etc...)
> Hi Renaud --
>
> This is an unfortunate consequence of the 'initialize' method that your
> class inherits from ExpressionSet. 'new' uses the prototype of 'A' to
> create .Object, and then passes .Object and other arguments to 'new'
> down to 'initialize'. The 'initialize' method inherited from
> ExpressionSet is in part
>
>> head(selectMethod(initialize, 'A'))
> 1 structure(function (.Object, ...)
> 2 {
> 3 .local<- function (.Object, assayData, phenoData, featureData,
> 4 exprs = new("matrix"), ...)
> 5 {
> 6 if (missing(assayData)) {
>
> with .local invoked so as .local(.Object, ...) in the body of
> initialize. So your 'eset' is the seen as the second argument, and
> matches by position with the argument 'assayData'; this is not expected
> to be an ExpressionSet, and trouble ensues. In retrospect the 'right'
> signature for initialize,ExpressionSet-method would have placed the
> named arguments after ..., with the user needing to supply named
> assayData= etc arguments.
>
> An additional problem is that the initialize,ExpressionSet-method
> assumes that .Object is from its prototype, so for instance an exprs
> with non-zero dimensions is overwritten
>
>> eset<- new("ExpressionSet", exprs=matrix(0,10,5))
>> eset
> ExpressionSet (storageMode: lockedEnvironment)
> assayData: 10 features, 5 samples
> element names: exprs
> protocolData: none
> phenoData: none
> featureData: none
> experimentData: use 'experimentData(object)'
> Annotation:
>> initialize(eset)
> ExpressionSet (storageMode: lockedEnvironment)
> assayData: 0 features, 0 samples
> element names: exprs
> protocolData: none
> phenoData: none
> featureData: none
> experimentData: use 'experimentData(object)'
> Annotation:
>
> You're stuck working with the initialize,ExpressionSet-method as defined
> (changing it now would disrupt a lot of package and user code), probably
> the easiest way being to write an appropriate initialize method or,
> probably better given the pitfalls of doing this correctly, write a
> constructor that does what you want
>
> library(Biobase)
> setClass('A', representation(extraslot='list'),
> contains='ExpressionSet',
> prototype=prototype(extraslot=list(a=1:5)))
>
> setGeneric("A", function(x, ...) standardGeneric("A"))
> setMethod(A, "missing", function(x, ...) new("A", ...))
> setMethod(A, "ExpressionSet", function(x, ...) {
> new("A", assayData=assayData(x), phenoData=phenoData(x),
> featureData=featureData(x), ...) ## protocalData here too?
> })
>
> ## test
> eset<- new('ExpressionSet', exprs=matrix(0, 10, 5))
> A(eset)
> A()
> A(eset)@extraslot
> A()@extraslot
> A(eset, extraslot=list(b=5:1))@extraslot
> A(extraslot=list(b=5:1))@extraslot
>
> Martin
>
>> Thank you for any insight on the matter.
>> Renaud
>>
>> sessionInfo:
>> R version 2.12.0 (2010-10-15)
>> Platform: x86_64-pc-linux-gnu (64-bit)
>>
>> locale:
>> [1] LC_CTYPE=en_ZA.utf8 LC_NUMERIC=C LC_TIME=en_ZA.utf8
>> LC_COLLATE=en_ZA.utf8 LC_MONETARY=C LC_MESSAGES=en_ZA.utf8
>> LC_PAPER=en_ZA.utf8
>> [8] LC_NAME=C LC_ADDRESS=C LC_TELEPHONE=C
>> LC_MEASUREMENT=en_ZA.utf8 LC_IDENTIFICATION=C
>>
>> attached base packages:
>> [1] stats graphics grDevices utils datasets methods base
>>
>> other attached packages:
>> [1] Biobase_2.8.0
>>
>>
>>
>>
>> ###
>> UNIVERSITY OF CAPE TOWN
>> This e-mail is subject to the UCT ICT policies and e-mai...{{dropped:5}}
>>
>> _______________________________________________
>> Bioconductor mailing list
>> Bioconductor at r-project.org
>> https://stat.ethz.ch/mailman/listinfo/bioconductor
>> Search the archives:
>> http://news.gmane.org/gmane.science.biology.informatics.conductor
>
###
UNIVERSITY OF CAPE TOWN
This e-mail is subject to the UCT ICT policies and e-mai...{{dropped:5}}
More information about the Bioconductor
mailing list