I'm trying to create a package for working on orientation data, i.e. data where the observations are 3D rotations. There are several different representations of orientations in common use: SO(3) matrices, Euler angles, unit quaternions, etc. One thing I'd like is to make it convenient to work in any representation, and have conversions to others done as needed. I'm trying to do all of this in S4 classes. Here's the current class structure I'm using; please let me know if there's something wrong with this: The base class is abstract. All representations will deal with vectors of orientations, but at this level I don't know how that will be implemented: setClass('orientation') setIs('orientation', 'vector') First questions: is this the way to say that orientations behave as vectors? Do I need to say that? Should I say that? One representation is as an SO(3) matrix (i.e. a 3x3 matrix with determinant 1). I have a descendant class that stores these in a 3 x 3 x n array: setClass('rotmatrix', representation(x = 'array')) setIs('rotmatrix','orientation') rotmatrix <- function(a) { d <- dim(a) if (length(d) < 3) d <- c(d,1) a <- array(a, d) stopifnot(dim(a)[1] == 3, dim(a)[2] == 3) new('rotmatrix', x = a) } Other representations have other storage methods, e.g. setClass('quaternion', representation(x = 'matrix')) setIs('quaternion', 'orientation') Now I want to make sure these work as vectors. I don't need to define a '[' method for the abstract base class, do I? I originally set this definition for the rotmatrix class: setMethod('[', 'rotmatrix', def = function(x, i) rotmatrix(x@x[,,i,drop=FALSE]) ) However, this gives warnings:>In method for function "[": Expanding the signature to >include omitted arguments in definition: j = "missing", >drop = "missing"I notice in the setMethod example the right way to do it: setMethod('[', 'rotmatrix', function(x, i, j, ..., drop) rotmatrix(x@x[,,i,drop=FALSE]) ) But where are the meanings for j and drop defined? Even if I don't declare orientation to be a vector, I get this warning, so where is it coming from? Is it good or bad to say that orientation is a vector? What implications does it have? Duncan Murdoch
Sounds like a nice example. Just a quick comment on one question before I have to run, will try to react more later. John Duncan Murdoch wrote:> > I'm trying to create a package for working on orientation data, i.e. > data where the observations are 3D rotations. > > There are several different representations of orientations in common > use: SO(3) matrices, Euler angles, unit quaternions, etc. One thing > I'd like is to make it convenient to work in any representation, and > have conversions to others done as needed. > > I'm trying to do all of this in S4 classes. Here's the current class > structure I'm using; please let me know if there's something wrong > with this: > > The base class is abstract. All representations will deal with > vectors of orientations, but at this level I don't know how that will > be implemented: > > setClass('orientation') > setIs('orientation', 'vector') > > First questions: is this the way to say that orientations behave as > vectors? Do I need to say that? Should I say that? > > One representation is as an SO(3) matrix (i.e. a 3x3 matrix with > determinant 1). I have a descendant class that stores these in a > 3 x 3 x n array: > > setClass('rotmatrix', representation(x = 'array')) > setIs('rotmatrix','orientation') > > rotmatrix <- function(a) { > d <- dim(a) > if (length(d) < 3) d <- c(d,1) > a <- array(a, d) > stopifnot(dim(a)[1] == 3, dim(a)[2] == 3) > new('rotmatrix', x = a) > } > > Other representations have other storage methods, e.g. > > setClass('quaternion', representation(x = 'matrix')) > setIs('quaternion', 'orientation') > > Now I want to make sure these work as vectors. I don't need to define > a '[' method for the abstract base class, do I? I originally set this > definition for the rotmatrix class: > > setMethod('[', 'rotmatrix', > def = function(x, i) rotmatrix(x@x[,,i,drop=FALSE]) > ) > > However, this gives warnings: > > >In method for function "[": Expanding the signature to > >include omitted arguments in definition: j = "missing", > >drop = "missing" > > I notice in the setMethod example the right way to do it: > > setMethod('[', 'rotmatrix', > function(x, i, j, ..., drop) rotmatrix(x@x[,,i,drop=FALSE]) > ) > > But where are the meanings for j and drop defined? Even if I don't > declare orientation to be a vector, I get this warning, so where is it > coming from? Is it good or bad to say that orientation is a vector? > What implications does it have?Actually, even though the message was a "warning", it really says what I think you want to do. The arguments j and drop arise in matrix or matrix-like objects (data.frame) and are in the generic so that methods can be dispatched (e.g.) on the column index argument. But in your case, indeed they had BETTER be missing, assuming they're meaningless in this example. So you could just accept the warning as a harmless nag (and maybe it should be a message rather than a warning in this case, but in other functions the omission might in fact have been a mistake). Or to be fastidious, you could supply the arguments with class "missing" in the signature to make explicit that the user had better not try to supply them. setMethod('[', signature(x='rotmatrix', j= 'missing', drop 'missing'), def = function(x, i) rotmatrix(x@x[,,i,drop=FALSE]) )> > Duncan Murdoch > > ______________________________________________ > R-devel@stat.math.ethz.ch mailing list > https://www.stat.math.ethz.ch/mailman/listinfo/r-devel-- John M. Chambers jmc@bell-labs.com Bell Labs, Lucent Technologies office: (908)582-2681 700 Mountain Avenue, Room 2C-282 fax: (908)582-3340 Murray Hill, NJ 07974 web: http://www.cs.bell-labs.com/~jmc
(better late than never, hopefully--a few comments on this example) Duncan Murdoch wrote:> > I'm trying to create a package for working on orientation data, i.e. > data where the observations are 3D rotations. > > There are several different representations of orientations in common > use: SO(3) matrices, Euler angles, unit quaternions, etc. One thing > I'd like is to make it convenient to work in any representation, and > have conversions to others done as needed. > > I'm trying to do all of this in S4 classes. Here's the current class > structure I'm using; please let me know if there's something wrong > with this: > > The base class is abstract. All representations will deal with > vectors of orientations, but at this level I don't know how that will > be implemented: > > setClass('orientation') > setIs('orientation', 'vector') > > First questions: is this the way to say that orientations behave as > vectors?It seems to say the right thing. 1) 'orientation' is a virtual class; 2) it extends 'vector', with no implication about the contents of either class and, since 'vector' is also virtual, no need to supply functions to coerce one to the other.> Do I need to say that? Should I say that?Yes to the second question. To be honest, it probably doesn't make much practical difference now, but it's the "right thing" to do, as I understand your example. The assertion is that for all 'orientation' objects, the vector computations ( principally "[", "[[", and length) are meaningful & so 'orientation' objects should inherit methods written for class "vector" in terms of such computations. In practice, there aren't many such methods, but there may be more sometime. Furthermore, there are many computations that are currently not methods but that should conceptually be methods for "vector". The function rev, e.g.: R> rev function (x) if (length(x) > 0) x[length(x):1] else x <environment: namespace:base> This should really not be applied to non-vectors, and the definition is in terms of vector computations. A related point is that "[", etc. currently apply to objects for which they are not conceptually meaningful. Objects representing calls to functions, for example. (Both R and S-Plus allow it. R gets credit for not allowing subsets of function objects, though, which S-Plus does allow.) R> ttt = quote(plot(x^2, y, pch ="+")) R> ttt[2:3] x^2(y) R> rev(ttt) "+"(y, x^2, plot) !! The behavior of [ is perhaps unlikely to be changed in base. But if one could optionally attach a more strict method-based package, I think it would make sense to restrict "[" to classes that extend "vector" (which includes, of course, the basic vector datatypes).> > One representation is as an SO(3) matrix (i.e. a 3x3 matrix with > determinant 1). I have a descendant class that stores these in a > 3 x 3 x n array: > > setClass('rotmatrix', representation(x = 'array')) > setIs('rotmatrix','orientation') > > rotmatrix <- function(a) { > d <- dim(a) > if (length(d) < 3) d <- c(d,1) > a <- array(a, d) > stopifnot(dim(a)[1] == 3, dim(a)[2] == 3) > new('rotmatrix', x = a) > } > > Other representations have other storage methods, e.g. > > setClass('quaternion', representation(x = 'matrix')) > setIs('quaternion', 'orientation') > > Now I want to make sure these work as vectors. I don't need to define > a '[' method for the abstract base class, do I?No, you don't need or want such a method. In fact, it would be nice to require that non-virtual classes extending 'orientation' DO have methods for "[" (and, presumably, length()? what about "[["?) There is a simple technique considered for the Omegahat OOP package that might be a useful addition in S4 methods as well. We would introduce a function, requireMethod, to force methods to be defined: requireMethod("[", "orientation") The function is just like setMethod, except without a method definition, and its effect is to generate an error for an object that dispatches this combination of function and signature. (Under the hood, it can just call setMethod with a method that produces an appropriate error message.) The idea seems to convey what we want for virtual classes such as 'orientation'. For example, by defining your method below for "rotmatrix", you satisfy the requirement, and block dispatch of the error method.> I originally set this > definition for the rotmatrix class: > > setMethod('[', 'rotmatrix', > def = function(x, i) rotmatrix(x@x[,,i,drop=FALSE]) > ) >... the rest was discussed before> Duncan Murdoch > > ______________________________________________ > R-devel@stat.math.ethz.ch mailing list > https://www.stat.math.ethz.ch/mailman/listinfo/r-devel-- John M. Chambers jmc@bell-labs.com Bell Labs, Lucent Technologies office: (908)582-2681 700 Mountain Avenue, Room 2C-282 fax: (908)582-3340 Murray Hill, NJ 07974 web: http://www.cs.bell-labs.com/~jmc