bio-nexml 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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