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,265 @@
1
+ module Bio
2
+ module NeXML
3
+ include LibXML
4
+
5
+ # Add a helper function to the array class.
6
+ Array.class_eval do
7
+
8
+ # Takes an array as argument and checks if that array is a subset of <tt>self</tt>.
9
+ # >> a = 1, 2, 3, 4, 5
10
+ # >> a.has? [1, 4]
11
+ # => true
12
+ # >> a.has? [2, 6]
13
+ # => false
14
+ # >> a.has? [1, 1]
15
+ # => true
16
+ def has?( arg )
17
+ arg.each { |a| return false unless include?( a ) }
18
+ true
19
+ end
20
+
21
+ end
22
+
23
+ # Add helper functions to XML::Node class.
24
+ XML::Node.class_eval do
25
+
26
+ # Assign namespaces to <tt>self</tt>.
27
+ # ---
28
+ # *Arguments*:
29
+ # * namespaces - a hash of prefix, uri pairs. It delegates the actual addition
30
+ # to the <tt>namespace=</tt> method.
31
+ # >> node = XML::Node.new( 'nexml' )
32
+ # >> node.namespaces = { :nex => "http://www.nexml.org/1.0" }
33
+ # >> node.namespaces = { nil => "http://www.nexml.org/1.0" }
34
+ # >> node
35
+ # => <nexml xmlns:nex="http://www.nexml.org/1.0" xmlns="http://www.nexml.org/1.0"/>
36
+ def namespaces=( namespaces )
37
+ namespaces.each do |prefix, prefix_uri|
38
+ self.namespace = prefix, prefix_uri
39
+ end
40
+ end
41
+
42
+ # Assign attributes to <tt>self</tt>.
43
+ # ---
44
+ # *Arguments*:
45
+ # * attributes - a hash of name, value pairs. It delegates the actual addition
46
+ # to the <tt>attribute=</tt> method.
47
+ # >> node = XML::Node.new( 'nexml' )
48
+ # >> node.attributes = { :version => '0.9' }
49
+ # >> node
50
+ # => <nexml version="0.9"/>
51
+ def attributes=( attributes )
52
+ attributes.each do |name, value|
53
+ self.attribute = name, value
54
+ end
55
+ end
56
+
57
+ # Assign a single attribte to <tt>self</tt>.
58
+ # ---
59
+ # *Arguments*:
60
+ # * pair - an array whose first value is the attribute's name and
61
+ # the second value is the attribute's value.
62
+ # >> node = XML::Node.new( 'nexml' )
63
+ # >> node.attribute = 'version', '0.9'
64
+ # >> node
65
+ # => <nexml version="0.9"/>
66
+ def attribute=( pair )
67
+ XML::Attr.new( self, pair.first.to_s, pair.last )
68
+ end
69
+
70
+ # Assing a single namespace to <tt>self</tt>.
71
+ # ---
72
+ # *Arguments*:
73
+ # * pair - an array whose first value is the namespace prefix and
74
+ # the second value is the namespace uri. Use <tt>nil</tt> as a prefix
75
+ # to create a default namespace.
76
+ # >> node = XML::Node.new( 'nexml' )
77
+ # >> node.namespace = 'nex', "http://www.nexml.org/1.0"
78
+ # >> node.namespace = nil, 'http://www.nexml.org/1.0'
79
+ # >> node
80
+ # => <nexml xmlns:nex="http://www.nexml.org/1.0" xmlns="http://www.nexml.org/1.0"/>
81
+ def namespace=( pair )
82
+ # have to check for a nil prefix
83
+ prefix = ( p = pair.first ) ? p.to_s : p
84
+ XML::Namespace.new( self, prefix, pair.last )
85
+ end
86
+
87
+ end
88
+
89
+ class Writer
90
+ # = DESCRIPTION
91
+ # Bio::NeXML::Writer class provides a wrapper over libxml-ruby to create any NeXML document.
92
+ # The document is populated with Bio::NeXML::* objects serialized to xml
93
+ # using their respective to_xml methods.
94
+ # To get the raw NeXML representation to_s method should be called on the return value.
95
+ # = EXAMPLES
96
+ # A lot of examples of creating nexml objects and then serializing them
97
+ # can be found in the tests "test/unit/bio/db/nexml/tc_writer.rb"
98
+ def initialize( filename = nil, indent = true )
99
+ @filename = filename
100
+ @indent = indent
101
+ @doc = XML::Document.new
102
+ @root = root
103
+ @doc.root = @root
104
+ end
105
+
106
+ # Add one or more <em>otus</em>, <em>trees</em>, or <em>characters</em> objects to <tt>self</tt>.
107
+ # This function delegates the actual addition to the <tt>otus=</tt>, <tt>trees=</tt>, or
108
+ # <tt>otus=</tt> methods.
109
+ # >> doc1 = Bio::NeXML::Parser.new 'test.xml'
110
+ # >> nexml = doc1.parse
111
+ # >> doc1.close
112
+ # >> writer = Bio::NeXML::Writer.new
113
+ # >> writer << nexml.otus
114
+ # >> writer << nexml.trees
115
+ # >> writer << nexml.characters
116
+ def <<( object )
117
+ test = object.instance_of?( Array ) ? object.first : object
118
+ case test
119
+ when Otus
120
+ self.otus = object
121
+ when Trees
122
+ self.trees = object
123
+ when Characters
124
+ self.characters = object
125
+ end
126
+ end
127
+
128
+ # Write to file.
129
+ # >> writer.save( 'sample.xml', true )
130
+ # ---
131
+ # Arguments:
132
+ # * filename( optional ) - the filename to write to. This need not be given if
133
+ # a filename was provided while initializing Writer.
134
+ # * indent( optional ) - wether to indent the output NeXML. This options assumes
135
+ # <tt>true</tt> by default.
136
+ def save( filename = nil, indent = false )
137
+ filename ||= @filename
138
+ indent ||= @indent
139
+ @doc.save( filename, :indent => indent )
140
+ end
141
+
142
+ # Add one or more <em>otus</em> objects to <tt>self</tt>.
143
+ # This function delegates the actual addition to <tt>add_otus</tt> method.
144
+ # >> writer = Bio::NeXML::Writer.new
145
+ # >> writer << nexml.otus
146
+ def otus=( otus )
147
+ if otus.instance_of? Array
148
+ otus.each{ |o| add_otus( o ) }
149
+ else
150
+ add_otus( otus )
151
+ end
152
+ end
153
+
154
+ # Add one or more <em>trees</em> objects to <tt>self</tt>.
155
+ # This function delegates the actual addition to <tt>add_trees</tt> method.
156
+ # >> writer = Bio::NeXML::Writer.new
157
+ # >> writer << nexml.trees
158
+ def trees=( trees )
159
+ if trees.instance_of? Array
160
+ trees.each{ |t| add_trees( t ) }
161
+ else
162
+ add_trees( trees )
163
+ end
164
+ end
165
+
166
+ # Add one or more <em>characters</em> objects to <tt>self</tt>.
167
+ # This function delegates the actual addition to <tt>add_characters</tt> method.
168
+ # >> writer = Bio::NeXML::Writer.new
169
+ # >> writer << nexml.characters
170
+ def characters=( characters )
171
+ if characters.instance_of? Array
172
+ characters.each{ |c| add_characters( c ) }
173
+ else
174
+ add_characters( characters )
175
+ end
176
+ end
177
+
178
+ # Add a single <em>otus</em> object to <tt>self</tt>.
179
+ # >> writer = Bio::NeXML::Writer.new
180
+ # >> writer.add_otus( nexml.otus.first )
181
+ def add_otus( otus )
182
+ @root << otus.to_xml
183
+ end
184
+
185
+ # Add a single <em>trees</em> object to <tt>self</tt>
186
+ # >> writer = Bio::NeXML::Writer.new
187
+ # >> writer.add_trees( nexml.trees.first )
188
+ def add_trees( trees )
189
+ @root << trees.to_xml
190
+ end
191
+
192
+ # Add a single <em>characters</em> object to <tt>self</tt>
193
+ # >> writer = Bio::NeXML::Writer.new
194
+ # >> writer.add_characters( nexml.characters.first )
195
+ def add_characters( characters )
196
+ @root << characters.to_xml
197
+ end
198
+
199
+ # Create the root <em>nexml</em> node.
200
+ # >> writer = Bio::NeXML::Writer.new
201
+ # >> writer.root
202
+ def root
203
+ root = create_node( "nexml", :"xsi:schemaLocation" => "http://www.nexml.org/2009 http://www.nexml.org/2009/xsd/nexml.xsd", :generator => "bioruby", :version => "0.9" )
204
+
205
+ root.namespaces = { nil => "http://www.nexml.org/2009", :xsi => "http://www.w3.org/2001/XMLSchema-instance", :xlink => "http://www.w3.org/1999/xlink", :nex => "http://www.nexml.org/2009" }
206
+ root
207
+ end
208
+
209
+ # Returns a hash of attributes for the given object.
210
+ # See example in unit tests.
211
+ def attributes( object, *names )
212
+ attributes = {}
213
+
214
+ names.each do |name|
215
+ case name
216
+ when :id
217
+ attributes[ name ] = object.send( name )
218
+ when :symbol
219
+ # a symbol maybe an integer or a string
220
+ # a length will always be a string
221
+ attributes[ name ] = object.send( name ).to_s
222
+ when :length
223
+ # a length will never be a string
224
+ value = object.send( name )
225
+ attributes[ name ] = value.to_s if value
226
+ when :label
227
+ # a label is optional so the returned value may be nil
228
+ value = object.send( name )
229
+ attributes[ name ] = value if value
230
+ when :"xsi:type"
231
+ attributes[ name ] = object.class.to_s.sub( /Bio::NeXML::/, 'nex:' )
232
+ when :otu, :otus, :states, :source, :target, :char
233
+ # an object is returned but in nexml we need the objects id
234
+ obj = object.send( name )
235
+ attributes[ name ] = obj.id if obj
236
+ when :state
237
+ # a state can be a complex object - use id
238
+ # or a string - use the same value
239
+ obj = object.send( name )
240
+ attributes[ name ] = obj.instance_of?( String ) ? obj : obj.id
241
+ when :root
242
+ value = object.send( :root? )
243
+ attributes[ name ] = value.to_s if value
244
+ end
245
+ end
246
+
247
+ attributes
248
+ end
249
+
250
+ # Create a XML::Node object with the given name and the attributes.
251
+ # >> writer = Bio::NeXML::Writer.new
252
+ # >> node = writer.send( :create_node, 'nexml', :version => '0.9' )
253
+ # >> node.to_s
254
+ # => "<nexml version=\"0.9\"/>"
255
+ def create_node( name, attributes = {} )
256
+ node = XML::Node.new( name )
257
+ node.attributes = attributes unless attributes.empty?
258
+ node
259
+ end
260
+
261
+ end #end class Parser
262
+
263
+ end #end module NeXML
264
+
265
+ end #end module Bio
@@ -0,0 +1,69 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+ <nex:nexml
3
+ version="0.9"
4
+ generator="eclipse"
5
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6
+ xmlns:xml="http://www.w3.org/XML/1998/namespace"
7
+ xmlns:nex="http://www.nexml.org/2009"
8
+ xmlns="http://www.nexml.org/2009"
9
+ xsi:schemaLocation="http://www.nexml.org/2009 http://www.nexml.org/2009/nexml.xsd">
10
+
11
+ <otus id="taxa1" label="A taxa block">
12
+ <otu id="o1" label="A taxon"/>
13
+ <otu id="o2" label="A taxon"/>
14
+ </otus>
15
+ <trees otus="taxa1" id="trees1" label="A tree container">
16
+ <tree id="tree1" xsi:type="nex:FloatTree" label="A float tree">
17
+ <node id="n1" label="A node" root="true" otu="o1"/>
18
+ <node id="n2" label="A node"/>
19
+ <rootedge id="re1" label="A rootedge" target="n1" length="0.5"/>
20
+ <edge source="n1" target="n2" id="e1" length="0.4353" label="An edge"/>
21
+ </tree>
22
+ <network id="network1" xsi:type="nex:IntNetwork" label="An int network">
23
+ <node id="n1n1" label="A node" root="true" otu="o1"/>
24
+ <node id="n1n2" label="A node"/>
25
+ <edge source="n1n1" target="n1n2" id="n1e1" length="1" label="An edge"/>
26
+ <edge source="n1n2" target="n1n2" id="n1e2" length="0" label="An edge"/>
27
+ </network>
28
+ </trees>
29
+ <characters otus="taxa1" id="standardchars6" xsi:type="nex:StandardSeqs" label="Standard sequences">
30
+ <format>
31
+ <states id="sss1">
32
+ <state id="ss1" symbol="1"/>
33
+ <state id="ss2" symbol="2"/>
34
+ <polymorphic_state_set symbol="4" id="ss4">
35
+ <member state="ss1"/>
36
+ <member state="ss2"/>
37
+ </polymorphic_state_set>
38
+ <uncertain_state_set symbol="5" id="ss5">
39
+ <member state="ss2"/>
40
+ <member state="ss1"/>
41
+ </uncertain_state_set>
42
+ </states>
43
+ <char states="sss1" id="sc1"/>
44
+ <char states="sss1" id="sc2"/>
45
+ </format>
46
+ <matrix>
47
+ <row id="sr1" otu="o1">
48
+ <seq>1 2</seq>
49
+ </row>
50
+ <row id="sr2" otu="o2">
51
+ <seq>2 2</seq>
52
+ </row>
53
+ </matrix>
54
+ </characters>
55
+ <characters otus="taxa1" id="m2" xsi:type="nex:StandardCells" label="Categorical characters">
56
+ <format>
57
+ <states id="sss2">
58
+ <state id="ss6" symbol="1"/>
59
+ </states>
60
+ <char states="sss2" id="sc3"/>
61
+ </format>
62
+
63
+ <matrix>
64
+ <row id="sr3" otu="o1">
65
+ <cell char="sc3" state="ss6"/>
66
+ </row>
67
+ </matrix>
68
+ </characters>
69
+ </nex:nexml>
@@ -0,0 +1,17 @@
1
+ require 'test/unit'
2
+ require 'bio/db/nexml'
3
+
4
+ module Bio
5
+ module NeXML
6
+ TEST_FILE = File.join(File.dirname(__FILE__), "data", "nexml", "test.xml" )
7
+ end
8
+ end
9
+
10
+ require File.join(File.dirname(__FILE__), "unit", "bio", "db", "nexml", 'tc_mapper' )
11
+ require File.join(File.dirname(__FILE__), "unit", "bio", "db", "nexml", 'tc_matrix' )
12
+ require File.join(File.dirname(__FILE__), "unit", "bio", "db", "nexml", 'tc_parser' )
13
+ require File.join(File.dirname(__FILE__), "unit", "bio", "db", "nexml", 'tc_taxa' )
14
+ require File.join(File.dirname(__FILE__), "unit", "bio", "db", "nexml", 'tc_trees' )
15
+ require File.join(File.dirname(__FILE__), "unit", "bio", "db", "nexml", 'tc_writer' )
16
+ require File.join(File.dirname(__FILE__), "unit", "bio", "db", "nexml", 'tc_factory' )
17
+
@@ -0,0 +1,119 @@
1
+ module Bio
2
+ module NeXML
3
+ class TestFactory < Test::Unit::TestCase
4
+ def setup
5
+ @nexml = Bio::NeXML::Nexml.new
6
+ @otus = @nexml.create_otus
7
+ end
8
+
9
+ def test_otus
10
+ assert @otus.kind_of? Bio::NeXML::Otus
11
+ end
12
+
13
+ def test_otu
14
+ otu = @otus.create_otu
15
+ assert otu.kind_of? Bio::NeXML::Otu
16
+ end
17
+
18
+ def test_trees
19
+ trees = @nexml.create_trees( :otus => @otus )
20
+ otu = @otus.create_otu
21
+ assert_equal @otus, trees.otus
22
+ assert trees.instance_of? Bio::NeXML::Trees
23
+
24
+ floattree = trees.create_tree
25
+ assert floattree.kind_of? Bio::NeXML::Tree
26
+ assert floattree.kind_of? Bio::Tree
27
+ assert floattree.kind_of? Bio::NeXML::FloatTree
28
+ floatnode = floattree.create_node( :otu => otu )
29
+ assert floatnode.kind_of? Bio::NeXML::Node
30
+ assert floatnode.kind_of? Bio::Tree::Node
31
+ assert_equal otu, floatnode.otu
32
+
33
+ floatedge = floattree.create_edge( :source => floatnode, :target => floatnode )
34
+ assert floatedge.kind_of? Bio::NeXML::Edge
35
+ assert floatedge.kind_of? Bio::Tree::Edge
36
+ assert floatedge.kind_of? Bio::NeXML::FloatEdge
37
+ floatrootedge = floattree.create_rootedge( :target => floatnode )
38
+ assert floatrootedge.kind_of? Bio::NeXML::Edge
39
+ assert floatrootedge.kind_of? Bio::Tree::Edge
40
+ assert floatrootedge.kind_of? Bio::NeXML::RootEdge
41
+ assert floatrootedge.kind_of? Bio::NeXML::FloatRootEdge
42
+
43
+ inttree = trees.create_tree( true )
44
+ assert inttree.kind_of? Bio::NeXML::Tree
45
+ assert inttree.kind_of? Bio::Tree
46
+ assert inttree.kind_of? Bio::NeXML::IntTree
47
+ intedge = inttree.create_edge
48
+ assert intedge.kind_of? Bio::NeXML::Edge
49
+ assert intedge.kind_of? Bio::Tree::Edge
50
+ assert intedge.kind_of? Bio::NeXML::IntEdge
51
+ introotedge = inttree.create_rootedge
52
+ assert introotedge.kind_of? Bio::NeXML::Edge
53
+ assert introotedge.kind_of? Bio::Tree::Edge
54
+ assert introotedge.kind_of? Bio::NeXML::RootEdge
55
+ assert introotedge.kind_of? Bio::NeXML::IntRootEdge
56
+
57
+ floatnetwork = trees.create_network
58
+ assert floatnetwork.kind_of? Bio::NeXML::Tree
59
+ assert floatnetwork.kind_of? Bio::Tree
60
+ assert floatnetwork.kind_of? Bio::NeXML::FloatNetwork
61
+ floatnedge = floatnetwork.create_edge
62
+ assert floatnedge.kind_of? Bio::NeXML::Edge
63
+ assert floatnedge.kind_of? Bio::Tree::Edge
64
+ assert floatnedge.kind_of? Bio::NeXML::FloatEdge
65
+
66
+ intnetwork = trees.create_network( true )
67
+ assert intnetwork.kind_of? Bio::NeXML::Tree
68
+ assert intnetwork.kind_of? Bio::Tree
69
+ assert intnetwork.kind_of? Bio::NeXML::IntNetwork
70
+ intnedge = intnetwork.create_edge
71
+ assert intnedge.kind_of? Bio::NeXML::Edge
72
+ assert intnedge.kind_of? Bio::Tree::Edge
73
+ assert intnedge.kind_of? Bio::NeXML::IntEdge
74
+ end
75
+ def test_characters_seqs
76
+ otu = @otus.create_otu
77
+ dnaseqs = @nexml.create_characters( "Dna", false, :otus => @otus )
78
+ assert dnaseqs.kind_of? Bio::NeXML::Characters
79
+ assert dnaseqs.kind_of? Bio::NeXML::Dna
80
+ assert dnaseqs.kind_of? Bio::NeXML::DnaSeqs
81
+ assert_equal @otus, dnaseqs.otus
82
+
83
+ format = dnaseqs.create_format
84
+ assert format.kind_of? Bio::NeXML::Format
85
+ assert_equal format, dnaseqs.format
86
+
87
+ matrix = dnaseqs.create_matrix
88
+ assert matrix.kind_of? Bio::NeXML::Matrix
89
+ assert matrix.kind_of? Bio::NeXML::SeqMatrix
90
+ assert_equal matrix, dnaseqs.matrix
91
+
92
+ row = matrix.create_row( :otu => otu )
93
+ assert row.kind_of? Bio::NeXML::Row
94
+ assert row.kind_of? Bio::NeXML::SeqRow
95
+ assert_equal otu, row.otu
96
+
97
+ seq = 'ACATGCAG'
98
+ newrow = dnaseqs.create_raw( seq )
99
+ assert_equal newrow.sequences.first.value, seq
100
+ end
101
+ def test_characters_cells
102
+ otu1 = @otus.create_otu
103
+ otu2 = @otus.create_otu
104
+ standardcells = @nexml.create_characters( "Standard", true, :otus => @otus )
105
+ newrow1 = standardcells.create_raw('1 2 3 4 5')
106
+ newrow1.otu = otu1
107
+ newrow2 = standardcells.create_raw('1 2 3 4 5')
108
+ newrow2.otu = otu2
109
+ assert_equal otu1, newrow1.otu
110
+ assert_equal otu2, newrow2.otu
111
+ assert newrow1.kind_of? Bio::NeXML::Row
112
+ assert newrow1.kind_of? Bio::NeXML::CellRow
113
+ assert standardcells.kind_of? Bio::NeXML::Characters
114
+ assert standardcells.kind_of? Bio::NeXML::Standard
115
+ assert standardcells.kind_of? Bio::NeXML::StandardCells
116
+ end
117
+ end
118
+ end
119
+ end