Skip to content
Prev 463 / 21312 Next

[Bioc-devel] prada package and eSet in Biobase

Hi Florian --

Florian Hahne <f.hahne at dkfz.de> writes:
It would be fine to define the validation function in the
class. Sometimes the validity checking function is useful in other
circumstances, and it would then be less convenient to access and
reuse it.
Using specific element names makes expectation about what assayData
should contain clear. It also separates the use of the class from the
implementation details of the way elements are stored.

More technically, as suggested by assayDataNew (rather than "new"),
the AssayData class is a little special. It is a class union of list
and environment. Classes cannot 'contain' environments.

setClass("A", contains="AssayData")
[1] "A"
An object of class "A"
logical(0)
Error in validObject(new("A")) : invalid class "A" object: invalid
object for slot ".Data" in class "A": got class "logical", should be
or extend class "AssayData"

For this reason, one cannot instantiate or derive useful classes from
AssayData -- it serves as a predicate to identify objects that can
occupy the assayData slot, and for method dispatch purposes. Other
classes can have useful derived subclasses. So for instance one could
derive a subclass from "AnnotatedDataFrame"

setClass("B", representation(myX="numeric"),contains="AnnotatedDataFrame")

and use that to define a specialized class derived from eSet:

setClass("BSet", representation(phenoData="B"), contains="eSet",
         prototype(phenoData=new("B")))

setMethod("initialize","BSet", function(.Object, ...) {
  callNextMethod()
})
Error in checkSlotAssignment(object, name, value) : 
	assignment of an object of class "AnnotatedDataFrame" is not valid for slot 'phenoData' in an object of class "BSet"; is(value, "B") is not TRUE

In essence, and in contrast to the other slots, the responsibility for
controlling initialization of the assayData slot lies with eSet. 

On a related note, probably a slightly better implementation of
"initialize" for SwirlSet is

setMethod("initialize", "SwirlSet",
          function(.Object,
                   phenoData = new("AnnotatedDataFrame"),
                   experimentData = new("MIAME"),
                   annotation = character(),
                   R = new("matrix"),
                   G = new("matrix"),
                   Rb = new("matrix"),
                   Gb = new("matrix"),
                   ... ) {
            callNextMethod(.Object,
                           phenoData = phenoData,
                           experimentData = experimentData,
                           annotation = annotation,
                           R=R, G=G, Rb=Rb, Gb=Gb,
                           ...)
          })
The problem is exactly the one you noted above: it is not unreasonable
to expect that a user (or developer of Biobase) might want to alter an
object in several steps:

myFancyFunction <- function(obj) {
  assayData(obj) <- fancyAssaydData # obj invalid...
  phenoData(obj) <- justAsFancyPhenoData # but now valid
  validObject(obj)
  obj
}

This would not be possible if validity were checked at each
replacement. Probably it would encourage developers to access slots
directly, and this would be very bad when the underlying reprsentation
of the class changed.
Great questions, and I hope I haven't lied too much in trying to
answer them.

Martin