generic functions

Issue #47 resolved
Lars Skjærven created an issue

can we make a generic function dccm, and rename the current dccm to dccm.xyz ?

`dccm` <-
function(x, ...) {
 if(inherits(x, "matrix")) {
   class(x) <- c("matrix", "xyz")
   UseMethod("dccm", x)
 }
 else
   UseMethod("dccm")
}

Same also for mktrj.pca and mktrj.nma so that we can call mktrj( nma ) and mktrj( pca ) ?

Comments (10)

  1. Barry Grant

    Great idea, I like it! - but, what should we call our tentative new dccm.mean() function then...

    dccm.mean <-
    function(cij, cutoff.sims = dim(cij)[3], cutoff.cij = 0.4) {
    
      ## Check if bio3d package is uploaded
      oops <- require(bio3d)
      if (!oops) {
        warning("bio3d package missing: Please install, see: ?install.packages")
      }
    
      ## Check input is a 3d array
      if (length(dim(cij)) != 3) {
        stop("Input 'cij' should be a NxNxS 3d array, where N is the number of atoms and S is the number of simulations")
      }
      ## Check input is built of simmetric matrices
      if (dim(cij)[1] != dim(cij)[2]) {
        stop("Input 'cij' should be a NxNxS 3d array, where N is the number of atoms. The matrix uploaded is not NxNxS")
      }
      if (cutoff.sims > dim(cij)[3]) {
        stop("The cutoff.sims number is greater than the number of simulations in the cij matrix")
      }
    
      ## Filter by cutoff.cij and sum across simulations
      cut.cij.inds <- (abs(cij) < cutoff.cij)
      count <- array(NA, dim = dim(cij))
      count[!cut.cij.inds] = 1
      cij.sum <- apply(count, c(1:2), sum, na.rm = TRUE)
    
      ## Mask cij values below cutoff and average across simulations
      cij[cut.cij.inds] = NA
      cij.ave <- apply(cij, c(1:2), mean, na.rm = TRUE)
    
      ## Mask average values if below cutoff.sims
      cut.sims.inds <- (cij.sum < cutoff.sims)
      cij.ave[cut.sims.inds] = 0 ## Could use NA here
    
      class(cij.ave) = c("dccm", "matrix")
      return(cij.ave)
    }
    
  2. Lars Skjærven reporter

    beats me.. how about this non-elegant work around:

    `dccm` <-
    function(x, ...) {
     if(inherits(x, "matrix")) {
       class(x) <- c("matrix", "xyz")
       UseMethod("dccm", x)
     }
     else if(inherits(x, "array")) {
       class(x) <- c("matrix", "mean")
       UseMethod("dccm", x)
     }
     else
       UseMethod("dccm")
    }
    
  3. Lars Skjærven reporter

    hmm.. how should we make these s3 functions?

    I have in dccm.Rd

    \name{dccm}
    \alias{dccm}
    \title{ DCCM: Dynamical Cross-Correlation Matrix }
    \description{
      Determine the cross-correlations of atomic displacements. 
    }
    \usage{
    dccm(x, ...)
    }
    

    and e.g. in dccm.xyz.Rd:

    \name{dccm.xyz}
    \alias{dccm.xyz}
    \title{ DCCM: Dynamical Cross-Correlation Matrix }
    \description{
      Determine the cross-correlations of atomic displacements.
    }
    \usage{
    \method{dccm}{xyz}(x, reference = apply(xyz, 2, mean), grpby=NULL, ncore=1, nseg.scale=1, ...)
    }
    

    so that xyz has been renamed to x, and \dots are added :-P

    any preference?

  4. Barry Grant

    This looks good Lars. Having these consistent in terms of input argument names and of course all documented together in one dccm.Rd file (with an \alias{} entry for dccm.xyz() and dccm.nma()) is a good way to go I think.

    So currently, if we have a input x from nma() it will have class="nma" and we will be good with calling dccm.nma(). A similar think could happen with output from nma.pdbs(). However, if we have a regular numeric matrix from fit.xyz() or similar that does not have a class="xyz" then do we need to define some dccm.default() that just calls dccm.xyz()? Or should we just rename dccm.xyz() to dccm.default()?

    Perhaps this is not even an issue...

  5. Lars Skjærven reporter

    All in one .Rd file, like this? I was afraid that would be a bit messy..?

    \name{dccm}
    \alias{dccm}
    \alias{dccm.xyz}
    \alias{dccm.nma}
    \title{ DCCM: Dynamical Cross-Correlation Matrix }
    \description{
      Determine the cross-correlations of atomic displacements. 
    }
    \usage{
    dccm(x, ...)
    
    \method{dccm}{xyz}(x, reference = apply(xyz, 2, mean), grpby=NULL, ncore=1, nseg.scale=1, ...)
    
    \method{dccm}{nma}(x, ...)
    }
    
  6. Barry Grant

    Perhaps it is messy - I thought it would be more organized. Is it messy because of the long list of \arguments{}. The start would look just like you have it and

    \arguments{
      \item{x}{ a numeric matrix of Cartesian coordinates with a row per
        structure/frame, which will br passed to \code{dccm.xyz()}. 
      Alternatively, an object of class \code{nma} as obtained from function 
      \code{nma} that will be passed to the  \code{dccm.nma()} function, 
      see below for examples. }
    ....
    }
    

    What do you think?

  7. Lars Skjærven reporter

    hmm.. not sure. I committed a suggestion now. I tried to put it into one Rd file, but reversed it because of the diverse arguments and examples. its not only dccm.xyz and dccm.nma, but also dccm.enma, and dccm.mean ? check it out and see how you like it

  8. Barry Grant

    I like it this way and can see its much clearer. Only improvement would be to add some more pointers to the individual functions within the "Details" section for dccm.Rd. This could have links similar to the "see also"section - which is missing plot.dccm(). Just with a sentence for what each one does.

    btw: I have plot.dccm2() on my list of things to improve...

  9. Log in to comment