bio 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/COPYING +56 -0
  2. data/COPYING.ja +51 -0
  3. data/ChangeLog +540 -0
  4. data/GPL +340 -0
  5. data/LEGAL +141 -0
  6. data/LGPL +504 -0
  7. data/README.rdoc +4 -2
  8. data/Rakefile +2 -2
  9. data/bioruby.gemspec +17 -29
  10. data/doc/Tutorial.rd +118 -90
  11. data/doc/Tutorial.rd.html +124 -87
  12. data/lib/bio/appl/blast.rb +2 -2
  13. data/lib/bio/appl/blast/format0.rb +1 -1
  14. data/lib/bio/appl/fasta.rb +5 -12
  15. data/lib/bio/appl/fasta/format10.rb +96 -6
  16. data/lib/bio/appl/gcg/msf.rb +11 -14
  17. data/lib/bio/appl/pts1.rb +0 -4
  18. data/lib/bio/appl/sim4/report.rb +50 -17
  19. data/lib/bio/db/biosql/biosql_to_biosequence.rb +10 -0
  20. data/lib/bio/db/biosql/sequence.rb +234 -298
  21. data/lib/bio/db/embl/embl.rb +0 -3
  22. data/lib/bio/db/genbank/common.rb +3 -1
  23. data/lib/bio/io/biosql/ar-biosql.rb +257 -0
  24. data/lib/bio/io/biosql/biosql.rb +39 -0
  25. data/lib/bio/io/biosql/config/database.yml +5 -4
  26. data/lib/bio/io/ncbirest.rb +12 -5
  27. data/lib/bio/io/pubmed.rb +5 -1
  28. data/lib/bio/io/sql.rb +43 -150
  29. data/lib/bio/sequence/compat.rb +5 -1
  30. data/lib/bio/util/restriction_enzyme/range/sequence_range/calculated_cuts.rb +6 -4
  31. data/lib/bio/version.rb +1 -1
  32. data/test/data/gcg/pileup-aa.msf +67 -0
  33. data/test/data/sim4/complement-A4.sim4 +43 -0
  34. data/test/data/sim4/simple-A4.sim4 +25 -0
  35. data/test/data/sim4/simple2-A4.sim4 +25 -0
  36. data/test/functional/bio/io/test_pubmed.rb +129 -0
  37. data/test/unit/bio/appl/bl2seq/test_report.rb +5 -5
  38. data/test/unit/bio/appl/gcg/test_msf.rb +154 -0
  39. data/test/unit/bio/appl/hmmer/test_report.rb +2 -2
  40. data/test/unit/bio/appl/sim4/test_report.rb +869 -0
  41. data/test/unit/bio/appl/test_blast.rb +1 -1
  42. data/test/unit/bio/db/biosql/tc_biosql.rb +110 -0
  43. data/test/unit/bio/db/biosql/ts_suite_biosql.rb +8 -0
  44. data/test/unit/bio/test_feature.rb +18 -17
  45. data/test/unit/bio/test_reference.rb +18 -18
  46. data/test/unit/bio/test_sequence.rb +1 -1
  47. metadata +18 -30
  48. data/lib/bio/io/biosql/biodatabase.rb +0 -64
  49. data/lib/bio/io/biosql/bioentry.rb +0 -29
  50. data/lib/bio/io/biosql/bioentry_dbxref.rb +0 -11
  51. data/lib/bio/io/biosql/bioentry_path.rb +0 -12
  52. data/lib/bio/io/biosql/bioentry_qualifier_value.rb +0 -10
  53. data/lib/bio/io/biosql/bioentry_reference.rb +0 -10
  54. data/lib/bio/io/biosql/bioentry_relationship.rb +0 -10
  55. data/lib/bio/io/biosql/biosequence.rb +0 -11
  56. data/lib/bio/io/biosql/comment.rb +0 -7
  57. data/lib/bio/io/biosql/dbxref.rb +0 -13
  58. data/lib/bio/io/biosql/dbxref_qualifier_value.rb +0 -12
  59. data/lib/bio/io/biosql/location.rb +0 -32
  60. data/lib/bio/io/biosql/location_qualifier_value.rb +0 -11
  61. data/lib/bio/io/biosql/ontology.rb +0 -10
  62. data/lib/bio/io/biosql/reference.rb +0 -9
  63. data/lib/bio/io/biosql/seqfeature.rb +0 -32
  64. data/lib/bio/io/biosql/seqfeature_dbxref.rb +0 -11
  65. data/lib/bio/io/biosql/seqfeature_path.rb +0 -11
  66. data/lib/bio/io/biosql/seqfeature_qualifier_value.rb +0 -20
  67. data/lib/bio/io/biosql/seqfeature_relationship.rb +0 -11
  68. data/lib/bio/io/biosql/taxon.rb +0 -12
  69. data/lib/bio/io/biosql/taxon_name.rb +0 -9
  70. data/lib/bio/io/biosql/term.rb +0 -27
  71. data/lib/bio/io/biosql/term_dbxref.rb +0 -11
  72. data/lib/bio/io/biosql/term_path.rb +0 -12
  73. data/lib/bio/io/biosql/term_relationship.rb +0 -13
  74. data/lib/bio/io/biosql/term_relationship_term.rb +0 -11
  75. data/lib/bio/io/biosql/term_synonym.rb +0 -10
@@ -5,7 +5,7 @@
5
5
  # Naohisa Goto <ng@bioruby.org>
6
6
  # License:: The Ruby License
7
7
  #
8
- # $Id: msf.rb,v 1.2 2007/04/05 23:35:39 trevor Exp $
8
+ # $Id:$
9
9
  #
10
10
  # = About Bio::GCG::Msf
11
11
  #
@@ -30,14 +30,13 @@ module Bio
30
30
  # Creates a new Msf object.
31
31
  def initialize(str)
32
32
  str = str.sub(/\A[\r\n]+/, '')
33
- if /^\!\![A-Z]+\_MULTIPLE\_ALIGNMNENT/ =~ str[/.*/] then
34
- @heading = str[/.*/] # '!!NA_MULTIPLE_ALIGNMENT 1.0' or like this
35
- str.sub!(/.*/, '')
36
- end
37
- str.sub!(/.*\.\.$/m, '')
38
- @description = $&.to_s.sub(/^.*\.\.$/, '').to_s
33
+ preamble, @data = str.split(/^\/\/$/, 2)
34
+ preamble.sub!(/\A\!\![A-Z]+\_MULTIPLE\_ALIGNMENT.*/, '')
35
+ @heading = $& # '!!NA_MULTIPLE_ALIGNMENT 1.0' or like this
36
+ preamble.sub!(/.*\.\.\s*$/m, '')
37
+ @description = $&.to_s.sub(/^.*\.\.\s*$/, '').to_s
39
38
  d = $&.to_s
40
- if m = /(.+)\s+MSF\:\s+(\d+)\s+Type\:\s+(\w)\s+(.+)\s+(Comp)?Check\:\s+(\d+)/.match(d) then
39
+ if m = /^(?:(.+)\s+)?MSF\:\s+(\d+)\s+Type\:\s+(\w)\s+(.+)\s+(Comp)?Check\:\s+(\d+)/.match(d) then
41
40
  @entry_id = m[1].to_s.strip
42
41
  @length = (m[2] ? m[2].to_i : nil)
43
42
  @seq_type = m[3]
@@ -45,10 +44,8 @@ module Bio
45
44
  @checksum = (m[6] ? m[6].to_i : nil)
46
45
  end
47
46
 
48
- str.sub!(/.*\/\/$/m, '')
49
- a = $&.to_s.split(/^/)
50
47
  @seq_info = []
51
- a.each do |x|
48
+ preamble.each_line do |x|
52
49
  if /Name\: / =~ x then
53
50
  s = {}
54
51
  x.scan(/(\S+)\: +(\S*)/) { |y| s[$1] = $2 }
@@ -56,7 +53,6 @@ module Bio
56
53
  end
57
54
  end
58
55
 
59
- @data = str
60
56
  @description.sub!(/\A(\r\n|\r|\n)/, '')
61
57
  @align = nil
62
58
  end
@@ -133,11 +129,12 @@ module Bio
133
129
  # parsing
134
130
  def do_parse
135
131
  return if @align
136
- a = @data.strip.split(/\n\n/)
132
+ a = @data.split(/\r?\n\r?\n/)
137
133
  @seq_data = Array.new(@seq_info.size)
138
134
  @seq_data.collect! { |x| Array.new }
139
135
  a.each do |x|
140
- b = x.split(/\n/)
136
+ next if x.strip.empty?
137
+ b = x.sub(/\A[\r\n]+/, '').split(/[\r\n]+/)
141
138
  nw = 0
142
139
  if b.size > @seq_info.size then
143
140
  if /^ +/ =~ b.shift.to_s
@@ -65,10 +65,6 @@ class PTS1
65
65
  # Output report.
66
66
  attr_reader :output
67
67
 
68
- # Used function name (Integer).
69
- # function_name = Bio::PTS1::FUNCTION.find_all {|k,v| v == pts1.function }[0][0]
70
- attr_reader :function
71
-
72
68
  # Short-cut for Bio::PTS1.new(Bio::PTS1::FUNCTION['METAZOA-specific'])
73
69
  def self.new_with_metazoa_function
74
70
  self.new('METAZOA-specific')
@@ -4,7 +4,7 @@
4
4
  # Copyright:: Copyright (C) 2004 GOTO Naohisa <ng@bioruby.org>
5
5
  # License:: The Ruby License
6
6
  #
7
- # $Id: report.rb,v 1.9 2007/04/05 23:35:40 trevor Exp $
7
+ # $Id:$
8
8
  #
9
9
  # The sim4 report parser classes.
10
10
  #
@@ -43,7 +43,7 @@ module Bio
43
43
  @hits = []
44
44
  @all_hits = []
45
45
  overrun = ''
46
- text.each("\n\nseq1 = ") do |str|
46
+ text.each_line("\n\nseq1 = ") do |str|
47
47
  str = str.sub(/\A\s+/, '')
48
48
  str.sub!(/\n(^seq1 \= .*)/m, "\n") # remove trailing hits for sure
49
49
  tmp = $1.to_s
@@ -161,7 +161,7 @@ module Bio
161
161
  attr_reader :percent_identity
162
162
 
163
163
  # Returns directions of mapping.
164
- # Maybe one of "->", "<-" or "" or nil.
164
+ # Maybe one of "->", "<-", "==" or "" or nil.
165
165
  # This would be a Bio::Sim4 specific method.
166
166
  attr_reader :direction
167
167
 
@@ -170,7 +170,7 @@ module Bio
170
170
  # Bio::Sim4::Report::Hit class.
171
171
  # Users shall not use it directly.
172
172
  def self.parse(str, aln)
173
- /^(\d+)\-(\d+)\s*\((\d+)\-(\d+)\)\s*([\d\.]+)\%\s*([\-\<\>]*)/ =~ str
173
+ /^(\d+)\-(\d+)\s*\((\d+)\-(\d+)\)\s*([\d\.]+)\%\s*([\-\<\>\=]*)/ =~ str
174
174
  self.new(Segment.new($1, $2, aln[0]),
175
175
  Segment.new($3, $4, aln[2]),
176
176
  aln[1], $5, $6)
@@ -198,6 +198,17 @@ module Bio
198
198
  aln[1])
199
199
  end
200
200
 
201
+ # Parses part of sim4 result text and creates a new SegmentPair
202
+ # object for regions which can not be aligned correctly.
203
+ # It is designed to be called internally from
204
+ # Bio::Sim4::Report::Hit class.
205
+ # Users shall not use it directly.
206
+ def self.both_intron(prev_e, e, aln)
207
+ self.new(Segment.new(prev_e.seq1.to+1, e.seq1.from-1, aln[0]),
208
+ Segment.new(prev_e.seq2.to+1, e.seq2.from-1, aln[2]),
209
+ aln[1])
210
+ end
211
+
201
212
  #--
202
213
  # Bio::BLAST::*::Report::Hsp compatible methods
203
214
  # Methods already defined: midline, percent_identity
@@ -318,7 +329,9 @@ module Bio
318
329
  exo << e
319
330
  if ai then
320
331
  # intron data in alignment
321
- if ai[2].strip.empty? then
332
+ if ai[1].strip.empty? then
333
+ i = SegmentPair.both_intron(prev_e, e, ai)
334
+ elsif ai[2].strip.empty? then
322
335
  i = SegmentPair.seq1_intron(prev_e, e, ai)
323
336
  else
324
337
  i = SegmentPair.seq2_intron(prev_e, e, ai)
@@ -338,29 +351,49 @@ module Bio
338
351
  # Parses alignment.
339
352
  def parse_align
340
353
  s1 = []; ml = []; s2 = []
354
+ blocks = []
355
+ blocks.push [ s1, ml, s2 ]
341
356
  dat = @data[1..-1]
342
357
  return unless dat
343
358
  dat.each do |str|
344
359
  a = str.split(/\r?\n/)
345
- a.shift
346
- if /^(\s*\d+\s*)(.+)$/ =~ a[0] then
347
- range = ($1.length)..($1.length + $2.strip.length - 1)
360
+ ruler = a.shift
361
+ # First line, for example,
362
+ # " 50 . : . : . : . : . :"
363
+ # When the number is 0, forced to be a separated block
364
+ if /^\s*(\d+)/ =~ ruler and $1.to_i == 0 and !ml.empty? then
365
+ s1 = []; ml = []; s2 = []
366
+ blocks.push [ s1, ml, s2 ]
367
+ end
368
+ # For example,
369
+ # " 190 GAGTCATGCATGATACAA CTTATATATGTACTTAGCGGCA"
370
+ # " ||||||||||||||||||<<<...<<<-||-|||||||||||||||||||"
371
+ # " 400 GAGTCATGCATGATACAACTT...AGCGCT ATATATGTACTTAGCGGCA"
372
+ if /^(\s*\d+\s)(.+)$/ =~ a[0] then
373
+ range = ($1.length)..($1.length + $2.chomp.length - 1)
348
374
  a.collect! { |x| x[range] }
349
375
  s1 << a.shift
350
376
  ml << a.shift
351
377
  s2 << a.shift
352
378
  end
353
379
  end #each
354
- alx = ml.join('').split(/([\<\>]+\.+[\<\>]+)/)
355
- seq1 = s1.join(''); seq2 = s2.join('')
356
- i = 0
357
- alx.collect! do |x|
358
- len = x.length
359
- y = [ seq1[i, len], x, seq2[i, len] ]
360
- i += len
361
- y
380
+ alx_all = []
381
+ blocks.each do |ary|
382
+ s1, ml, s2 = ary
383
+ alx = ml.join('').split(/([\<\>]+\.+[\<\>]+)/)
384
+ seq1 = s1.join(''); seq2 = s2.join('')
385
+ i = 0
386
+ alx.collect! do |x|
387
+ len = x.length
388
+ y = [ seq1[i, len], x, seq2[i, len] ]
389
+ i += len
390
+ y
391
+ end
392
+ # adds virtual intron information if necessary
393
+ alx_all.push([ '', '', '' ]) unless alx_all.empty?
394
+ alx_all.concat alx
362
395
  end
363
- @align = alx
396
+ @align = alx_all
364
397
  end
365
398
  private :parse_align
366
399
 
@@ -46,6 +46,9 @@ module Bio::Sequence::Adapter::BioSQL
46
46
  def_biosequence_adapter :date_created
47
47
 
48
48
  def_biosequence_adapter :date_modified
49
+ #do |bs|
50
+ # Date.parse(bs.date_modified.to_s).strftime("%d-%b-%Y").upcase
51
+ # end
49
52
 
50
53
  def_biosequence_adapter :division
51
54
 
@@ -63,5 +66,12 @@ module Bio::Sequence::Adapter::BioSQL
63
66
 
64
67
  def_biosequence_adapter :comments
65
68
 
69
+ def_biosequence_adapter :other_seqids do |orig|
70
+ orig.identifier.split(',').collect do |dblink|
71
+ database, id = dblink.split(':')
72
+ Bio::Sequence::DBLink.new(database,id)
73
+ end
74
+ end
75
+
66
76
  end #module Bio::Sequence::Adapter::BioSQL
67
77
 
@@ -1,8 +1,10 @@
1
1
 
2
2
  #TODO save on db reading from a genbank or embl object
3
3
  module Bio
4
- class SQL
5
-
4
+ class SQL
5
+
6
+
7
+
6
8
  class Sequence
7
9
  private
8
10
  # example
@@ -12,10 +14,10 @@ module Bio
12
14
  #molecule_type=value add a bioentry_qualifier value to the table
13
15
  #molecule_type_update(value, rank) update an entry of the table with an existing rank
14
16
  #the method inferr the qualifier term from the name of the first symbol, or you can specify a synonym to use
15
-
17
+
16
18
  #creating an object with to_biosql is transaction safe.
17
-
18
- #TODO: implement setting for more than a qualifier-vale.
19
+
20
+ #TODO: implement setting for more than a qualifier-vale.
19
21
  def self.bioentry_qualifier_anchor(sym, *args)
20
22
  options = args.first || Hash.new
21
23
  #options.assert_valid_keys(:rank,:synonym,:multi)
@@ -23,278 +25,305 @@ module Bio
23
25
  method_writer_operator = (sym.to_s+"=").to_sym
24
26
  method_writer_modder = (sym.to_s+"_update").to_sym
25
27
  synonym = options[:synonym].nil? ? sym.to_s : options[:synonym]
26
-
27
- #Bio::SQL::Term.create(:name=>synonym, :ontology=> Bio::SQL::Ontology.find_by_name('Annotation Tags')) unless Bio::SQL::Term.exists?(:name =>synonym)
28
+
29
+ #DELETE #Bio::SQL::Term.create(:name=>synonym, :ontology=> Bio::SQL::Ontology.find_by_name('Annotation Tags')) unless Bio::SQL::Term.exists?(:name =>synonym)
28
30
  send :define_method, method_reader do
29
31
  #return an array of bioentry_qualifier_values
30
32
  begin
31
- ontology_annotation_tags = Ontology.find_or_create_by_name('Annotation Tags')
32
- term = Term.find_or_create_by_name(:name => synonym, :ontology=> ontology_annotation_tags)
33
- bioentry_qualifier_values = @entry.bioentry_qualifier_values.find_all_by_term_id(term)
34
- bioentry_qualifier_values.map{|row| row.value} unless bioentry_qualifier_values.nil?
35
- rescue Exception => e
33
+ #DELETE ontology_annotation_tags = Ontology.find_or_create({:name=>'Annotation Tags'})
34
+ term = Term.first(:conditions=>["name = ?",synonym]) || Term.create({:name => synonym, :ontology=> Ontology.first(:conditions=>["name = ?",'Annotation Tags'])})
35
+ bioentry_qualifier_values = @entry.bioentry_qualifier_values.all(:conditions=>["term_id = ?",term.term_id])
36
+ data = bioentry_qualifier_values.map{|row| row.value} unless bioentry_qualifier_values.nil?
37
+ begin
38
+ # this block try to check if the data retrived is a
39
+ # Date or not and change it according to GenBank/EMBL format
40
+ # in that case return a string
41
+ # otherwise the []
42
+ Date.parse(data.to_s).strftime("%d-%b-%Y").upcase
43
+ rescue ArgumentError, TypeError, NoMethodError, NameError
44
+ data
45
+ end
46
+ rescue Exception => e
36
47
  puts "Reader Error: #{synonym} #{e.message}"
37
48
  end
38
49
  end
39
-
50
+
40
51
  send :define_method, method_writer_operator do |value|
41
52
  begin
42
- ontology_annotation_tags = Ontology.find_or_create_by_name('Annotation Tags')
43
- term = Term.find_or_create_by_name(:name => synonym, :ontology=> ontology_annotation_tags)
44
- datas = @entry.bioentry_qualifier_values.find_all_by_term_id(term.term_id)
53
+ #DELETE ontology_annotation_tags = Ontology.find_or_create({:name=>'Annotation Tags'})
54
+ term = Term.first(:conditions=>["name = ?",synonym]) || Term.create({:name => synonym, :ontology=> Ontology.first(:conditions=>["name = ?",'Annotation Tags'])})
55
+ datas = @entry.bioentry_qualifier_values.all(:conditions=>["term_id = ?",term.term_id])
45
56
  #add an element incrementing the rank or setting the first to 1
46
- @entry.bioentry_qualifier_values.create(:term_id=>term.term_id, :rank=>datas.empty? ? 1 : datas.last.rank.succ, :value=>value)
47
- rescue Exception => e
57
+ be_qu_va=@entry.bioentry_qualifier_values.build({:term=>term, :rank=>(datas.empty? ? 1 : datas.last.rank.succ), :value=>value})
58
+ be_qu_va.save
59
+ rescue Exception => e
48
60
  puts "WriterOperator= Error: #{synonym} #{e.message}"
49
61
  end
50
62
  end
51
-
63
+
52
64
  send :define_method, method_writer_modder do |value, rank|
53
65
  begin
54
- ontology_annotation_tags = Ontology.find_or_create_by_name('Annotation Tags')
55
- term = Term.find_or_create_by_name(:name => synonym, :ontology=> ontology_annotation_tags)
56
- data = @entry.bioentry_qualifier_values.find_by_term_id_and_rank(term.term_id, rank)
66
+ #DELETE ontology_annotation_tags = Ontology.find_or_create({:name=>'Annotation Tags'})
67
+ term = Term.first(:conditions=>["name = ?",synonym]) || Term.create({:name => synonym, :ontology=> Ontology.first(:conditions=>["name = ?",'Annotation Tags'])})
68
+ data = @entry.bioentry_qualifier_values.all(:term_id=>term.term_id, :rank=>rank)
57
69
  if data.nil?
58
70
  send method_writer_operator, value
59
71
  else
60
72
  data.value=value
61
- data.save!
73
+ data.save
62
74
  end
63
75
  rescue Exception => e
64
76
  puts "WriterModder Error: #{synonym} #{e.message}"
65
77
  end
66
78
  end
67
-
79
+
68
80
  end
81
+
69
82
  public
70
83
  attr_reader :entry
71
-
84
+
72
85
  def delete
86
+ #TODO: check is references connected to this bioentry are leaf or not.
87
+ #actually I think it should be more sofisticated, check if there are
88
+ #other bioentries connected to references; if not delete 'em
89
+ @entry.references.each { |ref| ref.delete if ref.bioentries.size==1}
73
90
  @entry.destroy
74
91
  end
75
-
92
+
76
93
  def get_seqfeature(sf)
77
-
94
+
78
95
  #in seqfeature BioSQL class
79
96
  locations_str = sf.locations.map{|loc| loc.to_s}.join(',')
80
97
  #pp sf.locations.inspect
81
- locations_str = "join(#{locations_str})" if sf.locations.count>1
98
+ locations_str = "join(#{locations_str})" if sf.locations.count>1
82
99
  Bio::Feature.new(sf.type_term.name, locations_str,sf.seqfeature_qualifier_values.collect{|sfqv| Bio::Feature::Qualifier.new(sfqv.term.name,sfqv.value)})
83
100
  end
84
-
101
+
85
102
  def length=(len)
86
103
  @entry.biosequence.length=len
87
104
  end
88
-
105
+
89
106
  def initialize(options={})
90
- options.assert_valid_keys(:entry, :biodatabase_id,:biosequence)
107
+ #options.assert_valid_keys(:entry, :biodatabase,:biosequence)
91
108
  return @entry = options[:entry] unless options[:entry].nil?
92
-
93
- return to_biosql(options[:biosequence], options[:biodatabase_id]) unless options[:biosequence].nil? or options[:biodatabase_id].nil?
94
-
109
+
110
+ return to_biosql(options[:biosequence], options[:biodatabase]) unless options[:biosequence].nil? or options[:biodatabase].nil?
111
+
95
112
  end
96
-
97
- def to_biosql(bs,biodatabase_id)
98
- #Transcaction works greatly!!!
99
113
 
100
- #
114
+ def to_biosql(bs,biodatabase)
115
+ #DELETE #Transcaction works greatly!!!
101
116
  begin
102
- Bioentry.transaction do
103
-
104
- @entry = Bioentry.new(:biodatabase_id=>biodatabase_id, :name=>bs.entry_id)
105
-
106
- puts "primary" if $DEBUG
107
- self.primary_accession = bs.primary_accession
108
-
109
- puts "def" if $DEBUG
110
- self.definition = bs.definition unless bs.definition.nil?
111
-
112
- puts "seqver" if $DEBUG
113
- self.sequence_version = bs.sequence_version || 0
114
-
115
- puts "divi" if $DEBUG
116
- self.division = bs.division unless bs.division.nil?
117
-
118
- @entry.save!
119
- puts "secacc" if $DEBUG
120
-
121
- bs.secondary_accessions.each do |sa|
122
- #write as qualifier every secondary accession into the array
123
- self.secondary_accessions = sa
124
- end unless bs.secondary_accessions.nil?
125
-
126
-
127
- #to create the sequence entry needs to exists
128
- puts "seq" if $DEBUG
129
- puts bs.seq if $DEBUG
130
- self.seq = bs.seq unless bs.seq.nil?
131
- puts "mol" if $DEBUG
132
-
133
- self.molecule_type = bs.molecule_type unless bs.molecule_type.nil?
134
- puts "dc" if $DEBUG
135
-
136
- self.data_class = bs.data_class unless bs.data_class.nil?
137
- puts "top" if $DEBUG
138
- self.topology = bs.topology unless bs.topology.nil?
139
- puts "datec" if $DEBUG
140
- self.date_created = bs.date_created unless bs.date_created.nil?
141
- puts "datemod" if $DEBUG
142
- self.date_modified = bs.date_modified unless bs.date_modified.nil?
143
- puts "key" if $DEBUG
144
-
145
- bs.keywords.each do |kw|
146
- #write as qualifier every secondary accessions into the array
147
- self.keywords = kw
148
- end unless bs.keywords.nil?
149
- #FIX: problem settinf taxon_name: embl has "Arabidopsis thaliana (thale cress)" but in taxon_name table there isn't this name. I must check if there is a new version of the table
150
- puts "spec" if $DEBUG
151
- self.species = bs.species unless bs.species.nil?
152
- puts "Debug: #{bs.species}" if $DEBUG
153
- puts "Debug: feat..start" if $DEBUG
154
-
155
- bs.features.each do |feat|
156
- self.feature=feat
157
- end unless bs.features.nil?
158
- puts "Debug: feat...end" if $DEBUG
159
-
160
- #TODO: add comments and references
161
- bs.references.each do |reference|
162
- # puts reference.inspect
163
- self.reference=reference
164
- end unless bs.references.nil?
165
-
166
- bs.comments.each do |comment|
167
- self.comment=comment
168
- end unless bs.comments.nil?
169
-
170
- end #transaction
117
+ #DELETE Bioentry.transaction do
118
+ @entry = biodatabase.bioentries.build({:name=>bs.entry_id})
119
+
120
+ puts "primary" if $DEBUG
121
+ self.primary_accession = bs.primary_accession
122
+
123
+ puts "def" if $DEBUG
124
+ self.definition = bs.definition unless bs.definition.nil?
125
+
126
+ puts "seqver" if $DEBUG
127
+ self.sequence_version = bs.sequence_version || 0
128
+
129
+ puts "divi" if $DEBUG
130
+ self.division = bs.division unless bs.division.nil?
131
+
132
+ puts "identifier" if $DEBUG
133
+ self.identifier = bs.other_seqids.collect{|dblink| "#{dblink.database}:#{dblink.id}"}.join(';') unless bs.other_seqids.nil?
134
+ @entry.save
135
+ puts "secacc" if $DEBUG
136
+
137
+ bs.secondary_accessions.each do |sa|
138
+ puts "#{sa}" if $DEBUG
139
+ #write as qualifier every secondary accession into the array
140
+ self.secondary_accessions = sa
141
+ end unless bs.secondary_accessions.nil?
142
+
143
+
144
+ #to create the sequence entry needs to exists
145
+ puts "seq" if $DEBUG
146
+ puts bs.seq if $DEBUG
147
+ self.seq = bs.seq unless bs.seq.nil?
148
+ puts "mol" if $DEBUG
149
+
150
+ self.molecule_type = bs.molecule_type unless bs.molecule_type.nil?
151
+ puts "dc" if $DEBUG
152
+
153
+ self.data_class = bs.data_class unless bs.data_class.nil?
154
+ puts "top" if $DEBUG
155
+ self.topology = bs.topology unless bs.topology.nil?
156
+ puts "datec" if $DEBUG
157
+ self.date_created = bs.date_created unless bs.date_created.nil?
158
+ puts "datemod" if $DEBUG
159
+ self.date_modified = bs.date_modified unless bs.date_modified.nil?
160
+ puts "key" if $DEBUG
161
+
162
+ bs.keywords.each do |kw|
163
+ #write as qualifier every secondary accessions into the array
164
+ self.keywords = kw
165
+ end unless bs.keywords.nil?
166
+
167
+ puts "spec" if $DEBUG
168
+ #self.species = bs.species unless bs.species.nil?
169
+ self.species = bs.species unless bs.species.empty?
170
+ puts "Debug: #{bs.species}" if $DEBUG
171
+ puts "Debug: feat..start" if $DEBUG
172
+
173
+ bs.features.each do |feat|
174
+ self.feature=feat
175
+ end unless bs.features.nil?
176
+
177
+ puts "Debug: feat...end" if $DEBUG
178
+ bs.references.each do |reference|
179
+ self.reference=reference
180
+ end unless bs.references.nil?
181
+
182
+ bs.comments.each do |comment|
183
+ self.comment=comment
184
+ end unless bs.comments.nil?
185
+
186
+ #DELETE end #transaction
171
187
  return self
172
188
  rescue Exception => e
173
189
  puts "to_biosql exception: #{e}"
174
190
  puts $!
175
- end #rescue
191
+ end #rescue
176
192
  end #to_biosql
177
-
178
-
179
- def name
193
+
194
+
195
+ def name
180
196
  @entry.name
181
197
  end
182
198
  alias entry_id name
183
-
199
+
184
200
  def name=(value)
185
201
  @entry.name=value
186
202
  end
187
203
  alias entry_id= name=
188
-
204
+
189
205
  def primary_accession
190
206
  @entry.accession
191
207
  end
192
-
208
+
193
209
  def primary_accession=(value)
194
210
  @entry.accession=value
195
211
  end
196
-
212
+
197
213
  #TODO def secondary_accession
198
214
  # @entry.bioentry_qualifier_values
199
215
  # end
200
-
216
+
201
217
  def organism
202
218
  @entry.taxon.nil? ? "" : "#{@entry.taxon.taxon_scientific_name.name}"+ (@entry.taxon.taxon_genbank_common_name ? "(#{@entry.taxon.taxon_genbank_common_name.name})" : '')
203
219
  end
204
220
  alias species organism
205
-
221
+
206
222
  def organism=(value)
207
- taxon_name=TaxonName.find_by_name_and_name_class(value.gsub(/\s+\(.+\)/,''),'scientific name')
223
+ #FIX there is a shortcut
224
+ taxon_name=TaxonName.first(:conditions=>["name = ? and name_class = ?",value.gsub(/\s+\(.+\)/,''),'scientific name'])
208
225
  if taxon_name.nil?
209
226
  puts "Error value doesn't exists in taxon_name table with scientific name constraint."
210
227
  else
211
228
  @entry.taxon_id=taxon_name.taxon_id
212
- @entry.save!
229
+ @entry.save
213
230
  end
214
231
  end
215
232
  alias species= organism=
216
-
233
+
217
234
  def database
218
235
  @entry.biodatabase.name
219
236
  end
220
-
237
+
221
238
  def database_desc
222
239
  @entry.biodatabase.description
223
240
  end
224
-
241
+
225
242
  def version
226
243
  @entry.version
227
244
  end
228
- alias sequence_version version
229
-
245
+ alias sequence_version version
246
+
230
247
  def version=(value)
231
248
  @entry.version=value
232
249
  end
233
250
  alias sequence_version= version=
234
-
251
+
235
252
  def division
236
253
  @entry.division
237
254
  end
255
+
238
256
  def division=(value)
239
257
  @entry.division=value
240
258
  end
241
-
259
+
242
260
  def description
243
261
  @entry.description
244
262
  end
245
263
  alias definition description
246
-
264
+
247
265
  def description=(value)
248
266
  @entry.description=value
249
267
  end
250
268
  alias definition= description=
251
-
269
+
252
270
  def identifier
253
271
  @entry.identifier
254
272
  end
255
-
273
+ alias other_seqids identifier
274
+
256
275
  def identifier=(value)
257
276
  @entry.identifier=value
258
277
  end
259
-
278
+
260
279
  bioentry_qualifier_anchor :data_class
261
280
  bioentry_qualifier_anchor :molecule_type, :synonym=>'mol_type'
262
281
  bioentry_qualifier_anchor :topology
263
- bioentry_qualifier_anchor :date_created
282
+ bioentry_qualifier_anchor :date_created
264
283
  bioentry_qualifier_anchor :date_modified, :synonym=>'date_changed'
265
284
  bioentry_qualifier_anchor :keywords, :synonym=>'keyword'
266
285
  bioentry_qualifier_anchor :secondary_accessions, :synonym=>'secondary_accession'
267
-
286
+
268
287
  def features
269
- @entry.seqfeatures.collect {|sf|
270
- self.get_seqfeature(sf)}
288
+ @entry.seqfeatures.collect do |sf|
289
+ self.get_seqfeature(sf)
290
+ end
271
291
  end
272
-
292
+
273
293
  def feature=(feat)
274
- #ToDo: avoid Ontology find here, probably more efficient create class variables
275
- type_term_ontology = Ontology.find_or_create_by_name('SeqFeature Keys')
276
- type_term = Term.find_or_create_by_name(:name=>feat.feature, :ontology=>type_term_ontology)
277
- source_term_ontology = Ontology.find_or_create_by_name('SeqFeature Sources')
278
- source_term = Term.find_or_create_by_name(:name=>'EMBLGenBankSwit',:ontology=>source_term_ontology)
279
- seqfeature = Seqfeature.create(:bioentry=>@entry, :source_term=>source_term, :type_term=>type_term, :rank=>@entry.seqfeatures.count.succ, :display_name=>'')
280
- #seqfeature.save!
294
+ #ToDo: avoid Ontology find here, probably more efficient create class variables
295
+ #DELETE type_term_ontology = Ontology.find_or_create({:name=>'SeqFeature Keys'})
296
+ puts "feature:type_term = #{feat.feature}" if $DEBUG
297
+ type_term = Term.first(:conditions=>["name = ?", feat.feature]) || Term.create({:name=>feat.feature, :ontology=>Ontology.first(:conditions=>["name = ?",'SeqFeature Keys'])})
298
+ #DELETE source_term_ontology = Ontology.find_or_create({:name=>'SeqFeature Sources'})
299
+ puts "feature:source_term" if $DEBUG
300
+ source_term = Term.first(:conditions=>["name = ?",'EMBLGenBankSwit'])
301
+ puts "feature:seqfeature" if $DEBUG
302
+ seqfeature = @entry.seqfeatures.build({:source_term=>source_term, :type_term=>type_term, :rank=>@entry.seqfeatures.count.succ, :display_name=>''})
303
+ seqfeature.save
304
+ puts "feature:location" if $DEBUG
281
305
  feat.locations.each do |loc|
282
- location = Location.new(:seqfeature=>seqfeature, :start_pos=>loc.from, :end_pos=>loc.to, :strand=>loc.strand, :rank=>seqfeature.locations.count.succ)
283
- location.save!
306
+ location = seqfeature.locations.build({:seqfeature=>seqfeature, :start_pos=>loc.from, :end_pos=>loc.to, :strand=>loc.strand, :rank=>seqfeature.locations.count.succ})
307
+ location.save
284
308
  end
285
- qual_term_ontology = Ontology.find_or_create_by_name('Annotation Tags')
309
+
310
+ #DELETE qual_term_ontology = Ontology.find_or_create({:name=>'Annotation Tags'})
311
+
312
+ puts "feature:qualifier" if $DEBUG
286
313
  feat.each do |qualifier|
287
- qual_term = Term.find_or_create_by_name(:name=>qualifier.qualifier, :ontology=>qual_term_ontology)
288
- qual = SeqfeatureQualifierValue.new(:seqfeature=>seqfeature, :term=>qual_term, :value=>qualifier.value.to_s, :rank=>seqfeature.seqfeature_qualifier_values.count.succ)
289
- qual.save!
314
+ #DELETE qual_term = Term.find_or_create({:name=>qualifier.qualifier}, {:ontology=>qual_term_ontology})
315
+ qual_term = Term.first(:conditions=>["name = ?", qualifier.qualifier]) || Term.create({:name=>qualifier.qualifier, :ontology=>Ontology.first(:conditions=>["name = ?", 'Annotation Tags'])})
316
+ qual = seqfeature.seqfeature_qualifier_values.build({:seqfeature=>seqfeature, :term=>qual_term, :value=>qualifier.value.to_s, :rank=>seqfeature.seqfeature_qualifier_values.count.succ})
317
+ qual.save
318
+
290
319
  end
291
320
  end
292
-
321
+
293
322
  #return the seqfeature mapped from BioSQL with a type_term like 'CDS'
294
323
  def cdsfeatures
295
324
  @entry.cdsfeatures
296
325
  end
297
-
326
+
298
327
  # Returns the sequence.
299
328
  # Returns a Bio::Sequence::Generic object.
300
329
 
@@ -302,39 +331,41 @@ module Bio
302
331
  s = @entry.biosequence
303
332
  Bio::Sequence::Generic.new(s ? s.seq : '')
304
333
  end
305
-
306
- def seq=(value)
307
334
 
335
+ def seq=(value)
336
+ #TODO: revise this piece of code.
308
337
  #chk which type of alphabet is, NU/NA/nil
309
338
  if @entry.biosequence.nil?
310
- # puts "intoseq1"
339
+ #DELETE puts "intoseq1"
311
340
  @entry.biosequence = Biosequence.new(:seq=>value)
312
- @entry.biosequence.save!
313
-
341
+ # biosequence = @entry.biosequence.build({:seq=>value})
342
+ @entry.biosequence.save
343
+ # biosequence.save
314
344
  else
315
345
  @entry.biosequence.seq=value
316
346
  end
317
347
  self.length=value.length
318
- #@entry.biosequence.length=value.length
319
- #break
320
- @entry.save!
348
+ #DELETE #@entry.biosequence.length=value.length
349
+ #DELETE #break
350
+ @entry.save
321
351
  end
322
-
352
+
353
+ #report parents and exclude info with "no rank". Now I report rank == class but ... Question ? Have to be reported taxonomy with rank=="class"?
323
354
  def taxonomy
324
355
  tax = []
325
- taxon = @entry.taxon
326
- while taxon and taxon.taxon_id != taxon.parent_taxon_id
327
- tax << taxon.taxon_scientific_name.name
356
+ taxon = Taxon.first(:conditions=>["taxon_id = ?",@entry.taxon.parent_taxon_id])
357
+ while taxon and taxon.taxon_id != taxon.parent_taxon_id and taxon.node_rank!='no rank'
358
+ tax << taxon.taxon_scientific_name.name if taxon.node_rank!='class'
328
359
  #Note: I don't like this call very much, correct with a relationship in the ref class.
329
- taxon = Taxon.find(taxon.parent_taxon_id)
360
+ taxon = Taxon.first(:conditions=>["taxon_id = ?",taxon.parent_taxon_id])
330
361
  end
331
362
  tax.reverse
332
363
  end
333
-
334
- def length
364
+
365
+ def length
335
366
  @entry.biosequence.length
336
367
  end
337
-
368
+
338
369
  def references
339
370
  #return and array of hash, hash has these keys ["title", "dbxref_id", "reference_id", "authors", "crc", "location"]
340
371
  #probably would be better to d a class refrence to collect these informations
@@ -342,7 +373,7 @@ module Bio
342
373
  hash = Hash.new
343
374
  hash['authors'] = bio_ref.reference.authors.gsub(/\.\s/, "\.\s\|").split(/\|/)
344
375
 
345
- hash['sequence_position'] = "#{bio_ref.start_pos}-#{bio_ref.end_pos}" if (bio_ref.start_pos and bio_ref.end_pos)
376
+ hash['sequence_position'] = "#{bio_ref.start_pos}-#{bio_ref.end_pos}" if (bio_ref.start_pos and bio_ref.end_pos)
346
377
  hash['title'] = bio_ref.reference.title
347
378
  hash['embl_gb_record_number'] = bio_ref.rank
348
379
  #TODO: solve the problem with specific comment per reference.
@@ -350,159 +381,64 @@ module Bio
350
381
  #take a look when location is build up in def reference=(value)
351
382
 
352
383
  bio_ref.reference.location.split('|').each do |element|
353
- key,value=element.split('=')
354
- hash[key]=value
384
+ key,value=element.split('=')
385
+ hash[key]=value
355
386
  end unless bio_ref.reference.location.nil?
356
387
 
357
388
  hash['xrefs'] = bio_ref.reference.dbxref ? "#{bio_ref.reference.dbxref.dbname}; #{bio_ref.reference.dbxref.accession}." : ''
358
389
  Bio::Reference.new(hash)
359
- end
390
+ end
360
391
  end
361
-
392
+
362
393
  def comments
363
394
  @entry.comments.map do |comment|
364
395
  comment.comment_text
365
396
  end
366
397
  end
367
398
 
368
-
369
- def reference=(value)
370
-
371
- locations=Array.new
372
- locations << "journal=#{value.journal}" unless value.journal.empty?
373
- locations << "volume=#{value.volume}" unless value.volume.empty?
374
- locations << "issue=#{value.issue}" unless value.issue.empty?
375
- locations << "pages=#{value.pages}" unless value.pages.empty?
376
- locations << "year=#{value.year}" unless value.year.empty?
377
- locations << "pubmed=#{value.pubmed}" unless value.pubmed.empty?
378
- locations << "medline=#{value.medline}" unless value.medline.empty?
379
- locations << "doi=#{value.doi}" unless value.doi.nil?
380
- locations << "abstract=#{value.abstract}" unless value.abstract.empty?
381
- locations << "url=#{value.url}" unless value.url.nil?
382
- locations << "mesh=#{value.mesh}" unless value.mesh.empty?
383
- locations << "affiliations=#{value.affiliations}" unless value.affiliations.empty?
384
- locations << "comments=#{value.comments.join('~')}"unless value.comments.nil?
385
- start_pos, end_pos = value.sequence_position ? value.sequence_position.gsub(/\s*/,'').split('-') : [nil,nil]
386
- reference=Reference.find_or_create_by_title(:title=>value.title, :authors=>value.authors.join(' '), :location=>locations.join('|'))
387
-
388
- bio_reference=BioentryReference.new(:bioentry=>@entry,:reference=>reference,:rank=>value.embl_gb_record_number, :start_pos=>start_pos, :end_pos=>end_pos)
389
- bio_reference.save!
390
- end
391
-
399
+ def reference=(value)
400
+ locations=Array.new
401
+ locations << "journal=#{value.journal}" unless value.journal.empty?
402
+ locations << "volume=#{value.volume}" unless value.volume.empty?
403
+ locations << "issue=#{value.issue}" unless value.issue.empty?
404
+ locations << "pages=#{value.pages}" unless value.pages.empty?
405
+ locations << "year=#{value.year}" unless value.year.empty?
406
+ locations << "pubmed=#{value.pubmed}" unless value.pubmed.empty?
407
+ locations << "medline=#{value.medline}" unless value.medline.empty?
408
+ locations << "doi=#{value.doi}" unless value.doi.nil?
409
+ locations << "abstract=#{value.abstract}" unless value.abstract.empty?
410
+ locations << "url=#{value.url}" unless value.url.nil?
411
+ locations << "mesh=#{value.mesh}" unless value.mesh.empty?
412
+ locations << "affiliations=#{value.affiliations}" unless value.affiliations.empty?
413
+ locations << "comments=#{value.comments.join('~')}"unless value.comments.nil?
414
+ start_pos, end_pos = value.sequence_position ? value.sequence_position.gsub(/\s*/,'').split('-') : [nil,nil]
415
+ reference= Reference.first(:conditions=>["title = ?",value.title]) || Reference.create({:title=>value.title,:authors=>value.authors.join(' '), :location=>locations.join('|')})
416
+ bio_reference=@entry.bioentry_references.build({:reference=>reference,:rank=>value.embl_gb_record_number, :start_pos=>start_pos, :end_pos=>end_pos})
417
+ bio_reference.save
418
+ end
419
+
392
420
  def comment=(value)
393
- comment=Comment.new(:bioentry=>@entry, :comment_text=>value, :rank=>@entry.comments.count.succ)
394
- comment.save!
421
+ #DELETE comment=Comment.new({:bioentry=>@entry, :comment_text=>value, :rank=>@entry.comments.count.succ})
422
+ comment = @entry.comments.build({:comment_text=>value, :rank=>@entry.comments.count.succ})
423
+ comment.save
395
424
  end
396
-
425
+
397
426
  def save
398
427
  #I should add chks for SQL errors
399
- @entry.biosequence.save!
400
- @entry.save!
428
+ @entry.biosequence.save
429
+ @entry.save
401
430
  end
402
431
  def to_fasta
403
- #prima erano 2 print in stdout, meglio ritornare una stringa in modo che poi ci si possa fare quello che si vuole
404
- #print ">" + accession + "\n"
405
- #print seq.gsub(Regexp.new(".{1,#{60}}"), "\\0\n")
406
- ">" + accession + "\n" + seq.gsub(Regexp.new(".{1,#{60}}"), "\\0\n")
432
+ ">" + accession + "\n" + seq.gsub(Regexp.new(".{1,#{60}}"), "\\0\n")
407
433
  end
408
-
434
+
409
435
  def to_fasta_reverse_complememt
410
- ">" + accession + "\n" + seq.reverse_complement.gsub(Regexp.new(".{1,#{60}}"), "\\0\n")
436
+ ">" + accession + "\n" + seq.reverse_complement.gsub(Regexp.new(".{1,#{60}}"), "\\0\n")
411
437
  end
412
-
413
-
414
-
438
+
415
439
  def to_biosequence
416
- Bio::Sequence.adapter(self,Bio::Sequence::Adapter::BioSQL)
440
+ Bio::Sequence.adapter(self,Bio::Sequence::Adapter::BioSQL)
417
441
  end
418
442
  end #Sequence
419
-
420
-
421
443
  end #SQL
422
444
  end #Bio
423
-
424
- #TODO create tests for sequence object, roundtrip of informations
425
-
426
- if __FILE__ == $0
427
-
428
- require 'bio'
429
- require 'bio/io/sql'
430
- require 'pp'
431
-
432
- # connection = Bio::SQL.establish_connection('bio/io/biosql/config/database.yml','development')
433
- connection = Bio::SQL.establish_connection({'development'=>{'database'=>"biorails_development", 'adapter'=>"postgresql", 'username'=>"rails", 'password'=>nil}},'development')
434
- databases = Bio::SQL.list_databases
435
-
436
- # parser = Bio::FlatFile.auto('/home/febo/Desktop/aj224122.embl')
437
- parser = Bio::FlatFile.auto('/home/febo/Desktop/aj224122.gb')
438
- #parser = Bio::FlatFile.auto('/home/febo/Desktop/aj224122.fasta')
439
-
440
- parser.each do |entry|
441
- biosequence = entry.to_biosequence
442
- result = Bio::SQL::Sequence.new(:biosequence=>biosequence,:biodatabase_id=>databases.first[:id]) unless Bio::SQL.exists_accession(biosequence.primary_accession)
443
-
444
- if result.nil?
445
- pp "The sequence is already present into the biosql database"
446
- else
447
- # pp "Sequence"
448
- puts result.to_biosequence.output(:genbank) #:embl
449
- result.delete
450
- end
451
- end
452
-
453
- if false
454
- sqlseq = Bio::SQL.fetch_accession('AJ224122')
455
- #only output tests.
456
- pp "Connection"
457
- pp connection
458
- pp "Seq in dbs"
459
- pp Bio::SQL.list_entries
460
- #; NC_003098
461
-
462
-
463
- #pp sqlseq
464
- pp sqlseq.entry.inspect
465
- pp "sequence"
466
- #pp Bio::Sequence.auto(sqlseq.seq)
467
- pp "entry_id"
468
- pp sqlseq.entry_id
469
-
470
- pp "primary"
471
- pp sqlseq.accession
472
- pp "secondary_accessions"
473
- pp sqlseq.secondary_accessions
474
- pp "molecule type"
475
- pp sqlseq.molecule_type
476
- pp "data_class"
477
- pp sqlseq.data_class
478
- pp "division"
479
- pp sqlseq.division
480
- # NOTE : Topology is not represented in biosql?
481
- pp "topology"
482
- #TODO: CIRCULAR this at present maps to bioentry_qualifier_value, though there are plans to make it a column in table biosequence.
483
- pp sqlseq.topology
484
- pp "version"
485
- pp sqlseq.version
486
- #sequence.date_created = nil #????
487
- pp "date modified"
488
- pp sqlseq.date_modified
489
- pp "definition"
490
- pp sqlseq.definition
491
- pp "keywords"
492
- pp sqlseq.keywords
493
- pp "species"
494
- pp sqlseq.organism
495
- #sequence.classification = self.taxonomy.to_s.sub(/\.\z/, '').split(/\s*\;\s*/)"
496
- pp "classification"
497
- pp sqlseq.taxonomy
498
- #sequence.organnella = nil # not used
499
- pp "comments"
500
- pp sqlseq.comments
501
- pp "references"
502
- pp sqlseq.references
503
- pp "features"
504
- pp sqlseq.features
505
- puts sqlseq.to_biosequence.output(:embl)
506
- end
507
- ##
508
- end