~ubuntu-branches/debian/stretch/r-cran-rnexml/stretch

« back to all changes in this revision

Viewing changes to R/simmap.R

  • Committer: Package Import Robot
  • Author(s): Andreas Tille
  • Date: 2016-04-08 13:58:39 UTC
  • Revision ID: package-import@ubuntu.com-20160408135839-ilq08z8v8p414qpn
Tags: upstream-2.0.6
ImportĀ upstreamĀ versionĀ 2.0.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# simmap.R
 
2
 
 
3
# if(!is.null(phy$maps))
 
4
## FIXME write the characters/states block (but not matrix block) as well.  
 
5
 
 
6
## FIXME support writing multiphylos, list of multiphylos to nexml 
 
7
 
 
8
 
 
9
#' simmap_to_nexml
 
10
#' 
 
11
#' simmap_to_nexml
 
12
#' @param phy a phy object containing simmap phy$maps element,
 
13
#'  from the phytools pacakge
 
14
#' @param state_ids a named character vector giving the state 
 
15
#'  names corresponding to the ids used to refer to each state
 
16
#'  in nexml.  If null ids will be generated and states taken from 
 
17
#'  the phy$states names. 
 
18
#' @return a nexml representation of the simmap
 
19
#' @export 
 
20
#' @import XML
 
21
#' @examples
 
22
#' data(simmap_ex)
 
23
#' phy <- nexml_to_simmap(simmap_ex)
 
24
#' nex <- simmap_to_nexml(phy) 
 
25
simmap_to_nexml <- function(phy, state_ids = NULL){
 
26
 
 
27
  
 
28
  ## Hack to deal with S3 class issues when coercing to S4
 
29
  if(class(phy) == c("simmap", "phylo"))
 
30
    class(phy) <- "phylo"
 
31
  
 
32
  ## Create the NeXML object
 
33
  nexml <- as(phy, "nexml")
 
34
 
 
35
  if(!is.null(phy$states)){
 
36
    nexml <- add_characters(data.frame(states = as.integer(as.factor(phy$states))), nexml)
 
37
    
 
38
    ## FIXME doesn't have states
 
39
    chars_ids <- get_state_maps(nexml)[[1]]
 
40
    char_id <- names(chars_ids)
 
41
    state_ids <-  reverse_map(chars_ids[[1]]) 
 
42
    # can assume no other states added yet since works on a phy, not nexml  
 
43
  }
 
44
 
 
45
 
 
46
  if(!is.null(phy$maps))
 
47
    nexml <- simmap_edge_annotations(maps = phy$maps, 
 
48
                                     nexml = nexml, 
 
49
                                     state_ids = state_ids, 
 
50
                                     char_id = char_id)
 
51
  
 
52
 
 
53
  nexml
 
54
}
 
55
 
 
56
 
 
57
simmap_edge_annotations <- function(maps, nexml, state_ids = NULL, char_id = "simmapped_trait"){
 
58
 
 
59
  
 
60
  ## if state ids are not given
 
61
  if(is.null(state_ids)){
 
62
    state_ids <- levels(as.factor(names(unlist(maps))))
 
63
    names(state_ids) <- state_ids
 
64
  }
 
65
 
 
66
 
 
67
  # Loop over all edges, adding the simmap annotation to each: 
 
68
  for(i in 1:length(nexml@trees[[1]]@tree[[1]]@edge)){
 
69
   ## FIXME check to assure this is always the correct order??
 
70
 
 
71
    ## Read the mapping of the current edge 
 
72
    edge_map <- maps[[i]]
 
73
 
 
74
    ## Generate the list of XML "stateChange" nodes 
 
75
    mapping <- lapply(1:length(edge_map), function(j){
 
76
      ##  A node has an id, a length and a state 
 
77
      meta(property = "simmap:stateChange", 
 
78
           children = list(meta(property = "simmap:order",
 
79
                                content = j),
 
80
                           meta(property = "simmap:length", 
 
81
                                content = edge_map[[j]]),
 
82
                           meta(property = "simmap:state", 
 
83
                                content = state_ids[[names(edge_map[j])]] )
 
84
                           )
 
85
           )
 
86
    })
 
87
 
 
88
    reconstruction <-meta(property = "simmap:reconstruction", 
 
89
                          children =c(list(meta(property="simmap:char", 
 
90
                                              content = char_id)),
 
91
                                           mapping))
 
92
  
 
93
  ## Insert the reconstructions into a <meta> element in each nexml edge
 
94
    nexml@trees[[1]]@tree[[1]]@edge[[i]]@meta <- 
 
95
      c(meta(type = "LiteralMeta",
 
96
             property = "simmap:reconstructions",
 
97
             children = list(reconstruction)))
 
98
  }
 
99
 
 
100
  ## Return the entire nexml object
 
101
 nexml <- add_namespaces(c(simmap = "https://github.com/ropensci/RNeXML/tree/master/inst/simmap.md"),
 
102
                        nexml)
 
103
 nexml 
 
104
}
 
105
 
 
106
 
 
107
 
 
108
 
 
109
 
 
110
## Returns list of multiPhylo ...
 
111
 
 
112
#' nexml_to_simmap
 
113
#'
 
114
#' nexml_to_simmap
 
115
#' @param nexml a nexml object
 
116
#' @return a simmap object (phylo object with a $maps element 
 
117
#'  for use in phytools functions).
 
118
#' @export 
 
119
#' @examples
 
120
#' data(simmap_ex)
 
121
#' phy <- nexml_to_simmap(simmap_ex)
 
122
#' nex <- simmap_to_nexml(phy) 
 
123
nexml_to_simmap <- function(nexml){
 
124
 
 
125
  ## Get the statemap, if available
 
126
 
 
127
  characters <- get_characters(nexml)
 
128
 
 
129
  ## loop over trees blocks
 
130
  out <- lapply(nexml@trees, function(trees){
 
131
    phys <- lapply(trees@tree, 
 
132
                   tree_to_simmap, 
 
133
                   get_otu_maps(nexml)[[trees@otus]],
 
134
                   get_state_maps(nexml)[[1]][[1]]
 
135
                  )
 
136
    phys <- lapply(phys, characters_to_simmap, characters)
 
137
 
 
138
    names(phys) <- NULL
 
139
    class(phys) <- "multiPhylo"
 
140
    phys 
 
141
  })
 
142
 
 
143
 
 
144
  if(length(out) == 1){
 
145
    if(length(out[[1]]) > 1){
 
146
      flatten_multiphylo(out)
 
147
    } else {
 
148
      out[[1]][[1]]
 
149
    }
 
150
  }
 
151
 
 
152
}
 
153
 
 
154
characters_to_simmap <- function(phy, characters){
 
155
  out <- as.character(characters[[1]]) # coerce factor to string
 
156
  names(out) <- rownames(characters) 
 
157
  phy$states <- out
 
158
  phy
 
159
}
 
160
 
 
161
 
 
162
# given the nexml tree:
 
163
tree_to_simmap <- function(tree, otus, state_maps = NULL){
 
164
  maps <- lapply(tree@edge, function(edge){
 
165
 
 
166
    reconstructions <- sapply(edge@meta, function(x) x@property == "simmap:reconstructions")
 
167
    if(any(reconstructions))
 
168
      reconstruction <- edge@meta[[which(reconstructions)]]@children 
 
169
 
 
170
    else {  # handle exceptions 
 
171
      warning("no simmap data found")
 
172
      return(toPhylo(tree, otus)) ## no simmap found
 
173
    }
 
174
 
 
175
 
 
176
#    lapply(reconstruction, function(reconstruction){ # for each reconstruction
 
177
          stateChange <- sapply(reconstruction[[1]]@children, function(x) x@property == "simmap:stateChange")
 
178
 
 
179
          values <- sapply(reconstruction[[1]]@children[which(stateChange)], function(stateChange){ 
 
180
                           # phytools only supports one reconstruction of one character per phy object
 
181
                        property <- sapply(stateChange@children, function(x) x@property)
 
182
                        names(stateChange@children) <- property # clean labels
 
183
                        sapply(stateChange@children, function(x) x@content)
 
184
          })
 
185
          out <- as.numeric(values["simmap:length", ])
 
186
          ordering <- as.numeric(values["simmap:order",])
 
187
          if(!is.null(state_maps))
 
188
            states <- state_maps[values["simmap:state", ]]
 
189
          else 
 
190
            states <- values["simmap:state", ]
 
191
 
 
192
          names(out) <- states
 
193
          out <- out[ordering] # sort according to explicit order
 
194
 
 
195
          out
 
196
 #   })
 
197
   
 
198
  })
 
199
  names(maps) <- NULL
 
200
  
 
201
  phy <- toPhylo(tree, otus)
 
202
  phy$maps <- maps
 
203
 
 
204
  ## create the rest of the maps elements
 
205
 
 
206
 
 
207
  ## Return phylo object
 
208
  phy
 
209
}
 
210
 
 
211
 
 
212
 
 
213
#' @name simmap_ex 
 
214
#' @title A nexml class R object that includes simmap annotations
 
215
#' @description A nexml object with simmap stochastic character mapping
 
216
#'  annotations added to the edges, for use with the RNeXML package
 
217
#'  parsing and serializing NeXML into formats that work with the ape and
 
218
#'  phytools packages. 
 
219
#' @docType data
 
220
#' @usage simmap_ex
 
221
#' @format a \code{nexml} instance
 
222
#' @source Simulated tree and stochastic character mapping based on 
 
223
#' Revell 2011 (doi:10.1111/j.2041-210X.2011.00169.x)
 
224
#' @author Carl Boettiger 
 
225
NULL
 
226
 
 
227
 
 
228
 
 
229
## Extend directly with XML representation instead of S4
 
230
 
 
231
#setClass("simmap:reconstructions",
 
232
#         slots = c(reconstruction = "ListOfreconstruction"))
 
233
#setClass("ListOfreconstruction", contains = "list")
 
234
#setClass("simmap:stateChange", contains = "IDTagged") 
 
235
#
 
236
 
 
237
 
 
238
 
 
239