bio-nexml 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/Gemfile +15 -0
  2. data/Gemfile.lock +24 -0
  3. data/LICENSE.txt +20 -0
  4. data/README.rdoc +47 -0
  5. data/Rakefile +55 -0
  6. data/TODO.txt +6 -0
  7. data/VERSION +1 -0
  8. data/bio-nexml.gemspec +126 -0
  9. data/extconf.rb +2 -0
  10. data/lib/bio-nexml.rb +0 -0
  11. data/lib/bio.rb +321 -0
  12. data/lib/bio/db/nexml.rb +109 -0
  13. data/lib/bio/db/nexml/mapper.rb +113 -0
  14. data/lib/bio/db/nexml/mapper/framework.rb +157 -0
  15. data/lib/bio/db/nexml/mapper/inflection.rb +99 -0
  16. data/lib/bio/db/nexml/mapper/repository.rb +59 -0
  17. data/lib/bio/db/nexml/matrix.rb +1046 -0
  18. data/lib/bio/db/nexml/parser.rb +622 -0
  19. data/lib/bio/db/nexml/schema/README.txt +21 -0
  20. data/lib/bio/db/nexml/schema/abstract.xsd +159 -0
  21. data/lib/bio/db/nexml/schema/characters/README.txt +1 -0
  22. data/lib/bio/db/nexml/schema/characters/abstractcharacters.xsd +361 -0
  23. data/lib/bio/db/nexml/schema/characters/characters.xsd +22 -0
  24. data/lib/bio/db/nexml/schema/characters/continuous.xsd +190 -0
  25. data/lib/bio/db/nexml/schema/characters/dna.xsd +282 -0
  26. data/lib/bio/db/nexml/schema/characters/protein.xsd +280 -0
  27. data/lib/bio/db/nexml/schema/characters/restriction.xsd +239 -0
  28. data/lib/bio/db/nexml/schema/characters/rna.xsd +283 -0
  29. data/lib/bio/db/nexml/schema/characters/standard.xsd +261 -0
  30. data/lib/bio/db/nexml/schema/external/sawsdl.xsd +21 -0
  31. data/lib/bio/db/nexml/schema/external/xhtml-datatypes-1.xsd +177 -0
  32. data/lib/bio/db/nexml/schema/external/xlink.xsd +75 -0
  33. data/lib/bio/db/nexml/schema/external/xml.xsd +145 -0
  34. data/lib/bio/db/nexml/schema/meta/README.txt +2 -0
  35. data/lib/bio/db/nexml/schema/meta/annotations.xsd +100 -0
  36. data/lib/bio/db/nexml/schema/meta/meta.xsd +294 -0
  37. data/lib/bio/db/nexml/schema/nexml.xsd +104 -0
  38. data/lib/bio/db/nexml/schema/taxa/README.txt +2 -0
  39. data/lib/bio/db/nexml/schema/taxa/taxa.xsd +39 -0
  40. data/lib/bio/db/nexml/schema/trees/README.txt +2 -0
  41. data/lib/bio/db/nexml/schema/trees/abstracttrees.xsd +135 -0
  42. data/lib/bio/db/nexml/schema/trees/network.xsd +113 -0
  43. data/lib/bio/db/nexml/schema/trees/tree.xsd +149 -0
  44. data/lib/bio/db/nexml/schema/trees/trees.xsd +36 -0
  45. data/lib/bio/db/nexml/taxa.rb +147 -0
  46. data/lib/bio/db/nexml/trees.rb +663 -0
  47. data/lib/bio/db/nexml/writer.rb +265 -0
  48. data/test/data/nexml/test.xml +69 -0
  49. data/test/test_bio-nexml.rb +17 -0
  50. data/test/unit/bio/db/nexml/tc_factory.rb +119 -0
  51. data/test/unit/bio/db/nexml/tc_mapper.rb +78 -0
  52. data/test/unit/bio/db/nexml/tc_matrix.rb +551 -0
  53. data/test/unit/bio/db/nexml/tc_parser.rb +21 -0
  54. data/test/unit/bio/db/nexml/tc_taxa.rb +118 -0
  55. data/test/unit/bio/db/nexml/tc_trees.rb +370 -0
  56. data/test/unit/bio/db/nexml/tc_writer.rb +633 -0
  57. metadata +253 -0
@@ -0,0 +1,113 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <xs:schema
3
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
4
+ targetNamespace="http://www.nexml.org/2009"
5
+ xmlns="http://www.nexml.org/2009"
6
+ elementFormDefault="qualified">
7
+ <xs:annotation>
8
+ <xs:documentation>
9
+ This module defines the components of networks, graphs
10
+ where edges have an in-degree that may exceed 1. The
11
+ types defined in this module are concrete implementations
12
+ that inherit from the abstract types in the <a href="../abstract">
13
+ abstract trees module
14
+ </a>. <br /><br />
15
+ Depending on the concrete subclass, edges in networks either
16
+ have lengths formatted as integers or lengths formatted as
17
+ floating point numbers.
18
+ </xs:documentation>
19
+ </xs:annotation>
20
+
21
+ <xs:include schemaLocation="abstracttrees.xsd"/>
22
+
23
+ <xs:complexType name="NetworkNode" abstract="false">
24
+ <xs:annotation>
25
+ <xs:documentation>
26
+ A concrete network node implementation.
27
+ </xs:documentation>
28
+ </xs:annotation>
29
+ <xs:complexContent>
30
+ <xs:restriction base="AbstractNode">
31
+ <xs:sequence minOccurs="1" maxOccurs="1">
32
+ <xs:element name="meta" type="Meta" minOccurs="0" maxOccurs="unbounded"/>
33
+ </xs:sequence>
34
+ </xs:restriction>
35
+ </xs:complexContent>
36
+ </xs:complexType>
37
+ <!--
38
+ <xs:complexType name="NetworkEdge" abstract="false">
39
+ <xs:annotation>
40
+ <xs:documentation>
41
+ A concrete network edge implementation, no length specified.
42
+ </xs:documentation>
43
+ </xs:annotation>
44
+ <xs:complexContent>
45
+ <xs:extension base="AbstractEdge"/>
46
+ </xs:complexContent>
47
+ </xs:complexType>
48
+ -->
49
+ <xs:complexType name="NetworkFloatEdge" abstract="false">
50
+ <xs:annotation>
51
+ <xs:documentation>
52
+ A concrete network edge implementation, with float edge.
53
+ </xs:documentation>
54
+ </xs:annotation>
55
+ <xs:complexContent>
56
+ <xs:restriction base="AbstractEdge">
57
+ <xs:sequence minOccurs="1" maxOccurs="1">
58
+ <xs:element name="meta" type="Meta" minOccurs="0" maxOccurs="unbounded"/>
59
+ </xs:sequence>
60
+ <xs:attribute name="length" type="xs:float"/>
61
+ </xs:restriction>
62
+ </xs:complexContent>
63
+ </xs:complexType>
64
+
65
+ <xs:complexType name="NetworkIntEdge" abstract="false">
66
+ <xs:annotation>
67
+ <xs:documentation>
68
+ A concrete network edge implementation, with int edge.
69
+ </xs:documentation>
70
+ </xs:annotation>
71
+ <xs:complexContent>
72
+ <xs:restriction base="AbstractEdge">
73
+ <xs:sequence minOccurs="1" maxOccurs="1">
74
+ <xs:element name="meta" type="Meta" minOccurs="0" maxOccurs="unbounded"/>
75
+ </xs:sequence>
76
+ <xs:attribute name="length" type="xs:integer"/>
77
+ </xs:restriction>
78
+ </xs:complexContent>
79
+ </xs:complexType>
80
+
81
+ <xs:complexType name="FloatNetwork" abstract="false">
82
+ <xs:annotation>
83
+ <xs:documentation>
84
+ A concrete network implementation, with floating point edge lengths.
85
+ </xs:documentation>
86
+ </xs:annotation>
87
+ <xs:complexContent>
88
+ <xs:restriction base="AbstractNetwork">
89
+ <xs:sequence minOccurs="1" maxOccurs="1">
90
+ <xs:element minOccurs="1" maxOccurs="unbounded" name="node" type="NetworkNode"/>
91
+ <xs:element minOccurs="1" maxOccurs="unbounded" name="edge" type="NetworkFloatEdge"/>
92
+ </xs:sequence>
93
+ </xs:restriction>
94
+ </xs:complexContent>
95
+ </xs:complexType>
96
+
97
+ <xs:complexType name="IntNetwork" abstract="false">
98
+ <xs:annotation>
99
+ <xs:documentation>
100
+ A concrete network implementation, with integer edge lengths.
101
+ </xs:documentation>
102
+ </xs:annotation>
103
+ <xs:complexContent>
104
+ <xs:restriction base="AbstractNetwork">
105
+ <xs:sequence minOccurs="1" maxOccurs="1">
106
+ <xs:element minOccurs="1" maxOccurs="unbounded" name="node" type="NetworkNode"/>
107
+ <xs:element minOccurs="1" maxOccurs="unbounded" name="edge" type="NetworkIntEdge"/>
108
+ </xs:sequence>
109
+ </xs:restriction>
110
+ </xs:complexContent>
111
+ </xs:complexType>
112
+
113
+ </xs:schema>
@@ -0,0 +1,149 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <xs:schema
3
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
4
+ targetNamespace="http://www.nexml.org/2009"
5
+ xmlns="http://www.nexml.org/2009"
6
+ elementFormDefault="qualified">
7
+ <xs:annotation>
8
+ <xs:documentation>
9
+ This module defines the components of trees, graphs
10
+ where edges have an in-degree that of 1. The
11
+ types defined in this module are concrete implementations
12
+ that inherit from the abstract types in the <a href="../abstract">
13
+ abstract trees module</a>.<br /><br />
14
+ Depending on the concrete subclass, edges in trees either
15
+ have lengths formatted as integers or lengths formatted as
16
+ floating point numbers.
17
+ </xs:documentation>
18
+ </xs:annotation>
19
+
20
+ <xs:include schemaLocation="abstracttrees.xsd"/>
21
+
22
+ <xs:complexType name="TreeNode" abstract="false">
23
+ <xs:annotation>
24
+ <xs:documentation>
25
+ A concrete node implementation.
26
+ </xs:documentation>
27
+ </xs:annotation>
28
+ <xs:complexContent>
29
+ <xs:restriction base="AbstractNode">
30
+ <xs:sequence minOccurs="1" maxOccurs="1">
31
+ <xs:element name="meta" type="Meta" minOccurs="0" maxOccurs="unbounded"/>
32
+ </xs:sequence>
33
+ </xs:restriction>
34
+ </xs:complexContent>
35
+ </xs:complexType>
36
+
37
+ <!--
38
+ <xs:complexType name="TreeEdge" abstract="false">
39
+ <xs:annotation>
40
+ <xs:documentation>
41
+ A concrete edge implementation, no length type specified.
42
+ </xs:documentation>
43
+ </xs:annotation>
44
+ <xs:complexContent>
45
+ <xs:extension base="AbstractEdge"/>
46
+ </xs:complexContent>
47
+ </xs:complexType>
48
+ -->
49
+ <xs:complexType name="TreeFloatEdge" abstract="false">
50
+ <xs:annotation>
51
+ <xs:documentation>
52
+ A concrete edge implementation, with float length.
53
+ </xs:documentation>
54
+ </xs:annotation>
55
+ <xs:complexContent>
56
+ <xs:restriction base="AbstractEdge">
57
+ <xs:sequence minOccurs="1" maxOccurs="1">
58
+ <xs:element name="meta" type="Meta" minOccurs="0" maxOccurs="unbounded"/>
59
+ </xs:sequence>
60
+ <xs:attribute name="length" type="xs:float"/>
61
+ </xs:restriction>
62
+ </xs:complexContent>
63
+ </xs:complexType>
64
+
65
+ <xs:complexType name="TreeFloatRootEdge" abstract="false">
66
+ <xs:annotation>
67
+ <xs:documentation>
68
+ A concrete root edge implementation, with float length.
69
+ </xs:documentation>
70
+ </xs:annotation>
71
+ <xs:complexContent>
72
+ <xs:restriction base="AbstractRootEdge">
73
+ <xs:sequence minOccurs="1" maxOccurs="1">
74
+ <xs:element name="meta" type="Meta" minOccurs="0" maxOccurs="unbounded"/>
75
+ </xs:sequence>
76
+ <xs:attribute name="length" type="xs:float"/>
77
+ </xs:restriction>
78
+ </xs:complexContent>
79
+ </xs:complexType>
80
+
81
+ <xs:complexType name="TreeIntEdge" abstract="false">
82
+ <xs:annotation>
83
+ <xs:documentation>
84
+ A concrete edge implementation, with int length.
85
+ </xs:documentation>
86
+ </xs:annotation>
87
+ <xs:complexContent>
88
+ <xs:restriction base="AbstractEdge">
89
+ <xs:sequence minOccurs="1" maxOccurs="1">
90
+ <xs:element name="meta" type="Meta" minOccurs="0" maxOccurs="unbounded"/>
91
+ </xs:sequence>
92
+ <xs:attribute name="length" type="xs:integer"/>
93
+ </xs:restriction>
94
+ </xs:complexContent>
95
+ </xs:complexType>
96
+
97
+ <xs:complexType name="TreeIntRootEdge" abstract="false">
98
+ <xs:annotation>
99
+ <xs:documentation>
100
+ A concrete root edge implementation, with int length.
101
+ </xs:documentation>
102
+ </xs:annotation>
103
+ <xs:complexContent>
104
+ <xs:restriction base="AbstractRootEdge">
105
+ <xs:sequence minOccurs="1" maxOccurs="1">
106
+ <xs:element name="meta" type="Meta" minOccurs="0" maxOccurs="unbounded"/>
107
+ </xs:sequence>
108
+ <xs:attribute name="length" type="xs:integer"/>
109
+ </xs:restriction>
110
+ </xs:complexContent>
111
+ </xs:complexType>
112
+
113
+ <xs:complexType name="FloatTree" abstract="false">
114
+ <xs:annotation>
115
+ <xs:documentation>
116
+ A concrete tree implementation, with floating point edge lengths.
117
+ </xs:documentation>
118
+ </xs:annotation>
119
+ <xs:complexContent>
120
+ <xs:restriction base="AbstractTree">
121
+ <xs:sequence minOccurs="1" maxOccurs="1">
122
+ <xs:element name="meta" type="Meta" minOccurs="0" maxOccurs="unbounded"/>
123
+ <xs:element minOccurs="1" maxOccurs="unbounded" name="node" type="TreeNode"/>
124
+ <xs:element minOccurs="0" maxOccurs="1" name="rootedge" type="TreeFloatRootEdge"/>
125
+ <xs:element minOccurs="1" maxOccurs="unbounded" name="edge" type="TreeFloatEdge"/>
126
+ </xs:sequence>
127
+ </xs:restriction>
128
+ </xs:complexContent>
129
+ </xs:complexType>
130
+
131
+ <xs:complexType name="IntTree" abstract="false">
132
+ <xs:annotation>
133
+ <xs:documentation>
134
+ A concrete tree implementation, with integer edge lengths.
135
+ </xs:documentation>
136
+ </xs:annotation>
137
+ <xs:complexContent>
138
+ <xs:restriction base="AbstractTree">
139
+ <xs:sequence minOccurs="1" maxOccurs="1">
140
+ <xs:element name="meta" type="Meta" minOccurs="0" maxOccurs="unbounded"/>
141
+ <xs:element minOccurs="1" maxOccurs="unbounded" name="node" type="TreeNode"/>
142
+ <xs:element minOccurs="0" maxOccurs="1" name="rootedge" type="TreeIntRootEdge"/>
143
+ <xs:element minOccurs="1" maxOccurs="unbounded" name="edge" type="TreeIntEdge"/>
144
+ </xs:sequence>
145
+ </xs:restriction>
146
+ </xs:complexContent>
147
+ </xs:complexType>
148
+
149
+ </xs:schema>
@@ -0,0 +1,36 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.nexml.org/2009"
3
+ xmlns="http://www.nexml.org/2009" elementFormDefault="qualified">
4
+ <xs:annotation>
5
+ <xs:documentation>
6
+ This module defines the complex type for a set of trees,
7
+ analogous to the "trees" block in NEXUS files. The module
8
+ includes the modules that define concrete instances of
9
+ <a href="../tree">tree</a> objects and of <a href="../network">network</a>
10
+ objects.
11
+ </xs:documentation>
12
+ </xs:annotation>
13
+
14
+ <xs:include schemaLocation="tree.xsd"/>
15
+ <xs:include schemaLocation="network.xsd"/>
16
+
17
+ <xs:complexType name="Trees" abstract="false" mixed="true">
18
+ <xs:annotation>
19
+ <xs:documentation>
20
+ A concrete container for tree objects.
21
+ </xs:documentation>
22
+ </xs:annotation>
23
+ <xs:complexContent mixed="true">
24
+ <xs:extension base="TaxaLinked">
25
+ <xs:sequence minOccurs="1" maxOccurs="1">
26
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
27
+ <xs:element name="network" type="AbstractNetwork" minOccurs="1"
28
+ maxOccurs="unbounded"/>
29
+ <xs:element name="tree" type="AbstractTree" minOccurs="1"
30
+ maxOccurs="unbounded"/>
31
+ </xs:choice>
32
+ </xs:sequence>
33
+ </xs:extension>
34
+ </xs:complexContent>
35
+ </xs:complexType>
36
+ </xs:schema>
@@ -0,0 +1,147 @@
1
+ module Bio
2
+ module NeXML
3
+ # = DESCRIPTION
4
+ # Otu represents a taxon; an implementation of the
5
+ # <em>Taxon</em>[http://nexml.org/nexml/html/doc/schema-1/taxa/taxa/#Taxon] type.
6
+ # An Otu must have an 'id' and may take an an optional 'label'.
7
+ # taxon1 = Bio::NeXML::Otu.new( 'taxon1', :label => 'Label for taxon1' )
8
+ # taxon1.id #=> 'taxon1'
9
+ # taxon1.label #=> 'Label for taxon1'
10
+ # taxon1.otus #=> otus object they belong to; see docs for Otus
11
+ class Otu
12
+ include Mapper
13
+ @@writer = Bio::NeXML::Writer.new
14
+
15
+ # A file level unique identifier.
16
+ attr_accessor :id
17
+
18
+ # A human readable description.
19
+ attr_accessor :label
20
+
21
+ # An otu is contained in otus.
22
+ belongs_to :otus
23
+
24
+ # An otu is referred to by several tree nodes.
25
+ has_n :nodes
26
+
27
+ has_n :rows
28
+
29
+ # Create a new otu.
30
+ # otu = Bio::NeXML::Otu.id( 'o1' )
31
+ # otu = Bio::NeXML::Otu.id( 'o1', :label => 'A label' )
32
+ def initialize( id, options = {}, &block )
33
+ @id = id
34
+ properties( options ) unless options.empty?
35
+ block.arity < 1 ? instance_eval( &block ) : block.call( self ) if block_given?
36
+ end
37
+
38
+ def to_xml
39
+ @@writer.create_node( "otu", @@writer.attributes( self, :id, :label ) )
40
+ end
41
+
42
+ end #end class Otu
43
+
44
+ # = DESCRIPTION
45
+ # Otus is a container for Otu objects; an implementation of the
46
+ # <em>Taxa</em>[http://nexml.org/nexml/html/doc/schema-1/taxa/taxa/#Taxa] type.
47
+ # An Otus must have an 'id' and may take an optional 'label'. Adding two or more Otu objects
48
+ # with the same 'id' to an Otus is not allowed. Doing so will overwrite the previous Otu object
49
+ # with the same the same 'id'.
50
+ # taxa1 = Bio::NeXML::Otus.new( 'taxa1', :label => 'Label for taxa1' )
51
+ # taxa1.id #=> 'taxa1'
52
+ # taxa1.label #=> 'Label for taxa1'
53
+ #
54
+ # taxon1 = Bio::NeXML::Otu.new( 'taxon1' )
55
+ # taxon2 = Bio::NeXML::Otu.new( 'taxon2' )
56
+ #
57
+ # taxa1 << taxon1 << taxon2
58
+ # taxa1.count #=> 2
59
+ # taxa1.each { |otu| puts otu.id }
60
+ # taxon2.otus #=> taxa1
61
+ # taxa1.include?( taxon1 ) #=> true
62
+ # taxa1.delete( taxon2 ) #=> taxon2
63
+ class Otus
64
+ include Enumerable
65
+ include Mapper
66
+ @@writer = Bio::NeXML::Writer.new
67
+
68
+ # A file level unique identifier.
69
+ attr_accessor :id
70
+
71
+ # A human readable description.
72
+ attr_accessor :label
73
+
74
+ belongs_to :nexml
75
+
76
+ has_n :otus
77
+ has_n :trees, :singularize => false
78
+ has_n :characters, :singularize => false
79
+
80
+ def initialize( id, options = {}, &block )
81
+ @id = id
82
+ properties( options ) unless options.empty?
83
+ block.arity < 1 ? instance_eval( &block ) : block.call( self ) if block_given?
84
+ end
85
+
86
+ # Returns an array of otu contained in <tt>self</tt>.
87
+ def otus; end if false # dummy for rdoc
88
+ # Taken an array of otu and adds it to <tt>self</tt>.
89
+ def otus=; end if false # dummy for rdoc
90
+
91
+ # Takes an otu object and appends it to <tt>self</tt>.
92
+ def <<( otu )
93
+ add_otu( otu )
94
+ self
95
+ end
96
+
97
+ # Creates and returns an otu after appending it to self
98
+ def create_otu( options = {} )
99
+ otu = Otu.new( Bio::NeXML.generate_id( Otu ), options )
100
+ self << otu
101
+ otu
102
+ end
103
+
104
+ # Takes an otu or its id and deletes it. Returns the object deleted or <tt>nil</tt>.
105
+ def delete( otu )
106
+ delete_otu( otu )
107
+ end
108
+
109
+ # Takes an otu or its id and returns <tt>true</tt> if it is contained in <tt>self</tt>.
110
+ def include?( object )
111
+ has_otu?( object )
112
+ end
113
+
114
+ # Returns the otu object with the given id; <tt>nil</tt> if an otu with the given id is not
115
+ # contained in <tt>self</tt>.
116
+ def []( id )
117
+ get_otu_by_id( id )
118
+ end
119
+
120
+ # Iterate over each otu in <tt>self</tt> passing it to the block given. If no block is provided,
121
+ # it returns an Enumerator.
122
+ def each( &block )
123
+ @otus.each( &block )
124
+ end
125
+
126
+ # Iterate over each otu in <tt>self</tt> passing the otu and its id to the block given. If no
127
+ # block is provided, it returns an Enumerator.
128
+ def each_with_id( &block )
129
+ @otus.each_with_id( &block )
130
+ end
131
+
132
+ # Return the number of otu in <tt>self</tt>.
133
+ def length
134
+ number_of_otus
135
+ end
136
+
137
+ def to_xml
138
+ node = @@writer.create_node( "otus", @@writer.attributes( self, :id, :label ) )
139
+ self.each do |otu|
140
+ node << otu.to_xml
141
+ end
142
+ node
143
+ end
144
+
145
+ end #end class Otus
146
+ end
147
+ end
@@ -0,0 +1,663 @@
1
+ require 'bio/tree'
2
+
3
+ module Bio
4
+ module NeXML
5
+
6
+ # Node represents a node of a Tree or a Network. A node must have a unique id. It may optionally
7
+ # have a human readable 'label' and may link to an 'otu'.
8
+ class Node < Bio::Tree::Node
9
+ include Mapper
10
+ @@writer = Bio::NeXML::Writer.new
11
+
12
+ def to_xml
13
+ @@writer.create_node( "node", @@writer.attributes( self, :id, :otu, :root, :label ) )
14
+ end
15
+
16
+ # A file level unique identifier.
17
+ attr_accessor :id
18
+
19
+ # Stores a boolean value to indicate a root node.
20
+ attr_accessor :root
21
+
22
+ # A human readable description.
23
+ attr_accessor :label
24
+
25
+ # A node may optionally refer to an Otu.
26
+ belongs_to :otu
27
+
28
+ # A node is deemed part of a Tree.
29
+ belongs_to :tree
30
+
31
+ # Create a new otu. Passing an 'id' is a must. While 'label' and 'otu' may be passed
32
+ # as an optional hash.
33
+ # node = Bio::NeXML::Node.new( 'node1' )
34
+ # node = Bio::NeXML::Node.new( 'node1', :label => 'A node' )
35
+ # node = Bio::NeXML::Node.new( 'node1', :label => 'A node', :otu => otu )
36
+ def initialize( id, options = {} )
37
+ super( id )
38
+ @id = id
39
+ properties( options ) unless options.empty?
40
+ block.arity < 1 ? instance_eval( &block ) : block.call( self ) if block_given?
41
+ end
42
+
43
+ # Return the otu to which the node links to.
44
+ def otu; end if false # dummy for rdoc
45
+
46
+ # Link the node to the given otu.
47
+ def otu=( otu ); end if false # dummy for rdoc
48
+
49
+ # Returns true if the node is a root node; false otherwise.
50
+ def root?
51
+ root
52
+ end
53
+ end #end class Node
54
+
55
+ # Edge connect two nodes of a tree or a network. An edge should have a unique id. It should have
56
+ # a 'source' and a 'target' node and optionally a 'length' may be assigned to it.
57
+ class Edge < Bio::Tree::Edge
58
+ include Mapper
59
+ @@writer = Bio::NeXML::Writer.new
60
+
61
+ def to_xml
62
+ @@writer.create_node( "edge", @@writer.attributes( self, :id, :source, :target, :length, :label ) )
63
+ end
64
+
65
+ # A file level unique identifier.
66
+ attr_accessor :id
67
+
68
+ # Source of the edge.
69
+ attr_accessor :source
70
+
71
+ # Target of the edge.
72
+ attr_accessor :target
73
+
74
+ # A human readable description.
75
+ attr_accessor :label
76
+
77
+ # A node is deemed part of a Tree.
78
+ belongs_to :tree
79
+
80
+ # Create a new edge.
81
+ # edge = Bio::NeXML::Edge.new( 'edge1' )
82
+ # edge = Bio::NeXML::Edge.new( 'edge1', :source => node1, :target => node2 )
83
+ # edge = Bio::NeXML::Edge.new( 'edge1', :source => node1, :target => node2, :length => 1 )
84
+ def initialize( id, options = {} )
85
+ super( length )
86
+ @id = id
87
+ properties( options ) unless options.empty?
88
+ block.arity < 1 ? instance_eval( &block ) : block.call( self ) if block_given?
89
+ end
90
+
91
+ # Return the length of an edge.
92
+ def length
93
+ distance
94
+ end
95
+
96
+ # Set the length of an edge.
97
+ def length=( length )
98
+ self.distance = length
99
+ end
100
+ end #end class Edge
101
+
102
+ # A rootedge is an edge without a source. It is used in context of coalescent trees. RootEdge
103
+ # inherits from Edge so the same functionality is available in rootedge too.
104
+ class RootEdge < Edge
105
+ @@writer = Bio::NeXML::Writer.new
106
+ def to_xml
107
+ @@writer.create_node( "rootedge", @@writer.attributes( self, :id, :target, :length, :label ) )
108
+ end
109
+
110
+ private :source=
111
+
112
+ def initialize( id, options = {} )
113
+ super
114
+ end
115
+ end
116
+
117
+ class FloatRootEdge < RootEdge
118
+ def initialize( id, options = {} )
119
+ super
120
+ end
121
+ def length
122
+ distance.to_f
123
+ end
124
+ end
125
+
126
+ class IntRootEdge < RootEdge
127
+ def initialize( id, options = {} )
128
+ super
129
+ end
130
+ def length
131
+ distance.to_i
132
+ end
133
+ end
134
+
135
+ # A float edge is an edge whose length is defined using a floating point
136
+ # number.
137
+ class FloatEdge < Edge
138
+ def initialize( id, options = {} )
139
+ super
140
+ end
141
+ def length
142
+ distance.to_f
143
+ end
144
+ end
145
+
146
+ # An int edge is an edge whose length is defined using an integer
147
+ class IntEdge < Edge
148
+ def initialize( id, options = {} )
149
+ super
150
+ end
151
+ def length
152
+ distance.to_i
153
+ end
154
+ end
155
+
156
+ # An NeXML tree. A tree must have a unique 'id'. It may optionally take a 'label' and a 'rootedge'.
157
+ # This class inherits from Bio::Tree; naturally its functionality is leveraged here.
158
+ class Tree < Bio::Tree
159
+ include Mapper
160
+ @@writer = Bio::NeXML::Writer.new
161
+
162
+ def to_xml
163
+ node = @@writer.create_node( "tree", @@writer.attributes( self, :id, :'xsi:type', :label ) )
164
+
165
+ self.each_node do |n|
166
+ node << n.to_xml
167
+ end
168
+
169
+ rootedge = self.rootedge
170
+ node << rootedge.to_xml if rootedge
171
+
172
+ self.each_edge do |edge|
173
+ node << edge.to_xml
174
+ end
175
+
176
+ node
177
+ end
178
+
179
+ def create_node( options = {} )
180
+ node = Node.new( Bio::NeXML.generate_id( Node ), options )
181
+ self << node
182
+ node
183
+ end
184
+
185
+ def create_edge( options = {} )
186
+ raise "This is supposed to be an abstract method"
187
+ end
188
+
189
+ def create_rootedge( options = {} )
190
+ raise "This is supposed to be an abstract method"
191
+ end
192
+
193
+ # A file level unique identifier.
194
+ attr_accessor :id
195
+
196
+ # A human readable description.
197
+ attr_accessor :label
198
+
199
+ # A rootedge to indicate a time span leading up to the root.
200
+ attr_accessor :rootedge
201
+
202
+ # A tree is contained in Trees.
203
+ belongs_to :trees
204
+
205
+ # A tree will contain n number of nodes.
206
+ has_n :nodes
207
+
208
+ # A tree will contain n number of edges joining the nodes.
209
+ has_n :edges
210
+
211
+ # Create a new tree.
212
+ # tree = Bio::NeXML::Tree.new( 'tree1' )
213
+ # tree = Bio::NeXML::Tree.new( 'tree1', :label => 'A tree' )
214
+ #
215
+ # nodes = %w|node1 node2 node3|.map{ |n| Bio::NeXML::Node.new( n ) }
216
+ # edge1 = Bio::NeXML::Edge.new( 'edge1', :source => nodes[0], :target => nodes[1] )
217
+ # edge2 = Bio::NeXML::Edge.new( 'edge2', :source => nodes[0], :target => nodes[2] )
218
+ #
219
+ # tree = Bio::NeXML::Tree.new( 'tree1', :nodes => nodes )
220
+ # tree = Bio::NeXML::Tree.new do |t|
221
+ # t.label = 'A tree'
222
+ # t.nodes = nodes
223
+ # t.edges = [ edge1, edge2 ]
224
+ # # or, t << edge1 << edge2
225
+ # # or, t.add_edge( edge1 ); t.add_edge( edge2 )
226
+ #
227
+ # root = Bio::NeXML::Node.new( 'root1', :root => true )
228
+ # rootedge = Bio::NeXML::RootEdge.new( 're1', :target => root )
229
+ #
230
+ # t << root # or, t.add_otu( root )
231
+ # t.rootedge = rootedge
232
+ # end
233
+ def initialize( id = nil, options = {}, &block )
234
+ super()
235
+ @id = id
236
+ properties( options ) unless options.empty?
237
+ block.arity < 1 ? instance_eval( &block ) : block.call( self ) if block_given?
238
+ end
239
+
240
+ # Returns an array of root nodes.
241
+ def roots
242
+ nodes.select{ |n| n.root? }
243
+ end
244
+
245
+ # Append a node or an edge to the tree. The method delegates the actuall addition to
246
+ # <tt>add_node</tt>, <tt>add_edge</tt> methods.
247
+ def <<( object )
248
+ case object
249
+ when Node
250
+ add_node( object )
251
+ when Edge
252
+ add_edge( object )
253
+ end
254
+ self
255
+ end
256
+
257
+ # :stopdoc:
258
+ alias __add_node__ add_node
259
+ # :startdoc:
260
+ # Add a node to the tree.
261
+ def add_node( node )
262
+ super( node )
263
+ __add_node__( node )
264
+ end
265
+
266
+ # :stopdoc:
267
+ alias __add_edge__ add_edge
268
+ # :startdoc:
269
+ # Add an edge to the tree.
270
+ def add_edge( edge )
271
+ super( edge.source, edge.target, edge )
272
+ __add_edge__( edge )
273
+ end
274
+
275
+ def add_rootedge( edge )
276
+ @rootedge = edge
277
+ end
278
+
279
+ # :stopdoc:
280
+ alias __delete_node__ delete_node
281
+ # :startdoc:
282
+
283
+ # Remove a node from the tree. Returns the deleted node. It automatically removes all edges
284
+ # connected to that node. Raises IndexError if the node is not found in the tree.
285
+ def remove_node( node )
286
+ return unless include?( node )
287
+ super( node )
288
+ __delete_node__( node )
289
+ end
290
+ alias delete_node remove_node
291
+
292
+ # :stopdoc:
293
+ alias __delete_edge__ delete_edge
294
+ # :startdoc:
295
+
296
+ # Remove an edge from the tree. Returns the edge deleted. If more than one edge exists between
297
+ # the source and the target, both of them will be removed. Raises IndexError if the edge is
298
+ # not found in the tree.
299
+ def remove_edge( edge )
300
+ return unless include?( edge )
301
+ super( edge.source, edge.target )
302
+ __delete_edge__( edge )
303
+ end
304
+ alias delete_edge remove_edge
305
+
306
+ # Fetch a node by the given id.
307
+ def get_node_by_id( id ); end if false # dummy for rdoc
308
+
309
+ # get_node_by_name is actually defined in Bio::Tree. I have aliased it to get_node_by_id
310
+ # as hash lookup is faster than searching through an enumerable.
311
+ alias get_node_by_name get_node_by_id
312
+
313
+ # Fetch an edge by the given id.
314
+ def get_edge_by_id( id ); end if false # dummy for rdoc
315
+
316
+ # Fetch a node, or an edge by its id.
317
+ def []( id )
318
+ get_node_by_id( id ) ||
319
+ get_edge_by_id( id )
320
+ end
321
+
322
+ # Returns true if the given node is a part of <tt>self</tt>.
323
+ def has_node?( node ); end if false # dummy for rdoc
324
+
325
+ # Returns true if the given edge is a part of <tt>self</tt>.
326
+ def has_edge?( edge ); end if false # dummy for rdoc
327
+
328
+ # Returns true if the given node or the edge object is a part of this tree; false otherwise.
329
+ def include?( object )
330
+ has_node?( object ) ||
331
+ has_edge?( object )
332
+ end
333
+ alias has? include?
334
+
335
+ # Iterate over each node. Return an Enumerator if no block is given.
336
+ def each_node( &block ); end if false # dummy for rdoc
337
+
338
+ # Iterate over each node passing id and the node itself to the given block.
339
+ # Returns an Enumerator if no block is given.
340
+ def each_node_with_id; end if false # dummy for rdoc
341
+
342
+ # Iterate over each edge. Return an Enumerator if no block is given.
343
+ def each_edge; end if false # :yield: edge
344
+
345
+ # Iterate over each node passing id and the node itself to the given block.
346
+ # Returns an Enumerator if no block is given.
347
+ def each_edge_with_id; end if false # dummy for rdoc
348
+
349
+ # Return the number of nodes in the tree.
350
+ def number_of_nodes; end if false #dummy for rdoc
351
+
352
+ # Return the number of edges in the tree.
353
+ def number_of_edges; end if false #dummy for rdoc
354
+
355
+ # :stopdoc:
356
+ # Following methods have been redifined from Bio::Tree to take advantage of multiple root
357
+ # nodes in NeXML. Since for each root a differrent solution is possible, the result returned
358
+ # is a ( root, solution) hash. The solution for each root is the same as that returned by its
359
+ # super method.
360
+ # :startdoc:
361
+
362
+ # Returns the parent of the given node corresponding to each root.
363
+ def parent( node, *roots )
364
+ if roots.empty?
365
+ raise IndexError, 'can not get parent for unrooted tree' if self.roots.empty?
366
+ roots = self.roots
367
+ end
368
+ parents = {}
369
+ roots.each do |r|
370
+ parents[ r ] = super( node, r )
371
+ end
372
+ parents
373
+ end
374
+
375
+ def children( node, *root )
376
+ if root.empty?
377
+ raise IndexError, 'can not get parent for unrooted tree' if self.root.empty?
378
+ root = self.root
379
+ end
380
+ childrens = {}
381
+ root.each do |r|
382
+ c = adjacent_nodes(node)
383
+ c.delete(parent(node, r)[ r ])
384
+ childrens[ r ] = c
385
+ end
386
+
387
+ childrens
388
+ end
389
+
390
+ def descendents( node, *root )
391
+ if root.empty?
392
+ raise IndexError, 'can not get parent for unrooted tree' if self.root.empty?
393
+ root = self.root
394
+ end
395
+ descendent = {}
396
+ root.each do |r|
397
+ descendent[ r ] = super( node, r )
398
+ end
399
+ descendent
400
+ end
401
+
402
+ def lowest_common_ancestor( node1, node2, *root )
403
+ if root.empty?
404
+ raise IndexError, 'can not get parent for unrooted tree' if self.root.empty?
405
+ root = self.root
406
+ end
407
+ lca = {}
408
+ root.each do |r|
409
+ lca[ r ] = super( node1, node2, r )
410
+ end
411
+ lca
412
+ end
413
+
414
+ def ancestors( node, *root )
415
+ if root.empty?
416
+ raise IndexError, 'can not get parent for unrooted tree' if self.root.empty?
417
+ root = self.root
418
+ end
419
+ ancestor = {}
420
+ root.each do |r|
421
+ ancestor[ r ] = super( node, r )
422
+ end
423
+ ancestor
424
+ end
425
+ end #end class Tree
426
+
427
+ class IntTree < Tree
428
+ def initialize( id = nil, options = {}, &block )
429
+ super
430
+ end
431
+
432
+ def add_edge( edge )
433
+ edge.length = edge.length.to_i
434
+ super
435
+ end
436
+
437
+ def create_edge( options = {} )
438
+ edge = IntEdge.new( Bio::NeXML.generate_id( IntEdge ), options )
439
+ self << edge
440
+ edge
441
+ end
442
+
443
+ def create_rootedge( options = {} )
444
+ rootedge = IntRootEdge.new( Bio::NeXML.generate_id( IntRootEdge ), options )
445
+ self << rootedge
446
+ rootedge
447
+ end
448
+
449
+ end
450
+
451
+ class FloatTree < Tree
452
+ def initialize( id = nil, options = {}, &block )
453
+ super
454
+ end
455
+
456
+ def add_edge( edge )
457
+ edge.length = edge.length.to_f
458
+ super
459
+ end
460
+
461
+ def create_edge( options = {} )
462
+ edge = FloatEdge.new( Bio::NeXML.generate_id( FloatEdge ), options )
463
+ self << edge
464
+ edge
465
+ end
466
+
467
+ def create_rootedge( options = {} )
468
+ rootedge = FloatRootEdge.new( Bio::NeXML.generate_id( FloatRootEdge ), options )
469
+ self << rootedge
470
+ rootedge
471
+ end
472
+
473
+ end
474
+
475
+ class Network < Tree
476
+ @@writer = Bio::NeXML::Writer.new
477
+ belongs_to :trees
478
+ def initialize( id, options = {}, &block )
479
+ super
480
+ end
481
+
482
+ def to_xml
483
+ node = @@writer.create_node( "network", @@writer.attributes( self, :id, :'xsi:type', :label ) )
484
+
485
+ self.each_node do |n|
486
+ node << n.to_xml
487
+ end
488
+
489
+ self.each_edge do |edge|
490
+ node << edge.to_xml
491
+ end
492
+
493
+ node
494
+ end
495
+ end
496
+
497
+ class IntNetwork < Network
498
+ def initialize( id, options = {}, &block )
499
+ super
500
+ end
501
+
502
+ def add_edge( edge )
503
+ edge.length = edge.length.to_i
504
+ super
505
+ end
506
+
507
+ def create_edge( options = {} )
508
+ edge = IntEdge.new( Bio::NeXML.generate_id( IntEdge ), options )
509
+ self << edge
510
+ edge
511
+ end
512
+
513
+ end
514
+
515
+ class FloatNetwork < Network
516
+ def initialize( id, options = {}, &block )
517
+ super
518
+ end
519
+
520
+ def add_edge( edge )
521
+ edge.length = edge.length.to_f
522
+ super
523
+ end
524
+
525
+ def create_edge( options = {} )
526
+ edge = FloatEdge.new( Bio::NeXML.generate_id( FloatEdge ), options )
527
+ self << edge
528
+ edge
529
+ end
530
+
531
+ end
532
+
533
+ class Trees
534
+ include Mapper
535
+ @@writer = Bio::NeXML::Writer.new
536
+
537
+ def to_xml
538
+ node = @@writer.create_node( "trees", @@writer.attributes( self, :id, :label, :otus ) )
539
+
540
+ self.each_tree do |tree|
541
+ node << tree.to_xml
542
+ end
543
+
544
+ self.each_network do |network|
545
+ node << network.to_xml
546
+ end
547
+
548
+ node
549
+ end
550
+
551
+ def create_tree( int = false, options = {} )
552
+ type = int ? Bio::NeXML::IntTree : Bio::NeXML::FloatTree
553
+ tree = type.new( Bio::NeXML.generate_id( type ), options )
554
+ self << tree
555
+ tree
556
+ end
557
+
558
+ def create_network( int = false, options = {} )
559
+ type = int ? Bio::NeXML::IntNetwork : Bio::NeXML::FloatNetwork
560
+ network = type.new( Bio::NeXML.generate_id( type ), options )
561
+ self << network
562
+ network
563
+ end
564
+
565
+ attr_accessor :id
566
+ attr_accessor :label
567
+
568
+ # A trees refers links to an otu.
569
+ belongs_to :otus
570
+
571
+ # Trees is a container for trees and networks.
572
+ has_n :trees
573
+ has_n :networks
574
+
575
+ belongs_to :nexml
576
+
577
+ # Create a trees object.
578
+ def initialize( id = nil, options = {}, &block )
579
+ @id = id
580
+ properties( options ) unless options.empty?
581
+ block.arity < 1 ? instance_eval( &block ) : block.call( self ) if block_given?
582
+ end
583
+
584
+ # Add a tree to self.
585
+ def add_tree; end if false # dummy for rdoc
586
+
587
+ # Add a networ to self.
588
+ def add_network; end if false # dummy for rdoc
589
+
590
+ # Add a tree or a network to self.
591
+ def <<( object )
592
+ case object
593
+ when Network
594
+ add_network( object )
595
+ when Tree
596
+ add_tree( object )
597
+ end
598
+ self
599
+ end
600
+
601
+ # Delete a tree from self.
602
+ def delete_tree; end if false # dummy for rdoc
603
+
604
+ # Delete a network from self.
605
+ def delete_network; end if false # dummy for rdoc
606
+
607
+ # Fetch a tree by id.
608
+ def get_tree_by_id; end if false # dummy for rdoc
609
+
610
+ # Fetch a network by id.
611
+ def get_network_by_id; end if false # dummy for rdoc
612
+
613
+ # Fetch a tree or a network by id.
614
+ def []( id )
615
+ get_tree_by_id( id ) ||
616
+ get_network_by_id( id )
617
+ end
618
+
619
+ # Returns true if tree is containes in self.
620
+ def has_tree?( tree ); end if false # dummy for rdoc
621
+
622
+ # Returns true if the given network is containes in self; false otherwise.
623
+ def has_network?( tree ); end if false # dummy for rdoc
624
+
625
+ def include?( object )
626
+ has_tree?( object ) ||
627
+ has_network?( object )
628
+ end
629
+ alias has? include?
630
+
631
+ # Returns the number of trees contained in self.
632
+ def number_of_trees; end if false # dummy for rdoc
633
+
634
+ # Returns the number of networks contained in self.
635
+ def number_of_networks; end if false # dummy for rdoc
636
+
637
+ # Returns total number of trees and networks.
638
+ def count
639
+ number_of_trees + number_of_networks
640
+ end
641
+ alias length count
642
+
643
+ # Iterate over each tree. Returns an Enumerator if no block is given.
644
+ def each_tree( &block ); end if false # dummy for rdoc
645
+
646
+ # Iterate over each tree passing the id and the tree itself to the block.
647
+ # Returns an Enumerator if no block is given.
648
+ def each_tree_with_id( &block ); end if false # dummy for rdoc
649
+
650
+ # Iterate over each network. Returns an Enumerator if no block is given.
651
+ def each_network( &block ); end if false # dummy for rdoc
652
+
653
+ # Iterate over each network passing the id and the tree itself to the block.
654
+ # Returns an Enumerator if no block is given.
655
+ def each_network_with_id( &block ); end if false # dummy for rdoc
656
+
657
+ # Iterate over each element. Returns an Enumerator if no block is given.
658
+ def each( &block )
659
+ @trees.merge( @networks ).each( &block )
660
+ end
661
+ end #end class Trees
662
+ end #end module NeXML
663
+ end #end module Bio