snp-search 2.2.0 → 2.3.0

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.
data/lib/snp-search.rb CHANGED
@@ -1,301 +1,39 @@
1
1
  require 'rubygems'
2
- gem "bio", "~> 1.4.2"
3
2
  require 'bio'
4
3
  require 'snp_db_models'
5
4
  require 'activerecord-import'
6
5
  require 'diff/lcs'
6
+ require 'create_methods'
7
+ require 'filter_ignore_snps_methods'
8
+ require 'output_information_methods'
7
9
 
8
- #This method guesses the reference sequence file format
9
- def guess_sequence_format(reference_genome)
10
- file_extension = File.extname(reference_genome).downcase
11
- file_format = nil
12
- case file_extension
13
- when ".gbk", ".genbank", ".gb"
14
- file_format = :genbank
15
- when ".embl", ".emb"
16
- file_format = :embl
17
- end
18
- return file_format
19
- end
20
-
21
- # A method to populate the database with the features (genes etc) and the annotations from the gbk/embl file.
22
- # We include all features that are not 'source' or 'gene' as they are repetitive info. 'CDS' is the gene.
23
- # The annotation table includes also the start and end coordinates of the CDS. The strand is also included. the 'locations' method is defined in bioruby under genbank. It must be required at the top (bio).
24
- #Also, the qualifier and value are extracted from the gbk/embl file and added to the database.
25
- def populate_features_and_annotations(sequence_file)
26
- puts "Adding features and their annotations...."
27
- ActiveRecord::Base.transaction do
28
- counter = 0
29
- sequence_file.features.each do |feature|
30
- counter += 1
31
- puts "Total number of features and annotations added: #{counter}" if counter % 100 == 0
32
- unless feature.feature == "source" || feature.feature == "gene"
33
- db_feature = Feature.new
34
- db_feature.start = feature.locations.first.from
35
- db_feature.end = feature.locations.first.to
36
- db_feature.strand = feature.locations.first.strand
37
- db_feature.name = feature.feature
38
- db_feature.save
39
- # Populate the Annotation table with qualifier information from the genbank file
40
- feature.qualifiers.each do |qualifier|
41
- a = Annotation.new
42
- a.qualifier = qualifier.qualifier
43
- a.value = qualifier.value
44
- a.save
45
- db_feature.annotations << a
46
- end
47
- end
48
- end
49
- end
50
- end
51
-
52
- #This method populates the rest of the information, i.e. SNP information, Alleles and Genotypes.
53
- def populate_snps_alleles_genotypes(vcf_file, cuttoff_snp, cuttoff_genotype)
54
-
55
- puts "Adding SNPs........"
56
- # open vcf file and parse each line
57
- File.open(vcf_file) do |f|
58
- # header names
59
- while line = f.gets
60
- if line =~ /CHROM/
61
- line.chomp!
62
- column_headings = line.split("\t")
63
- strain_names = column_headings[9..-1]
64
- strain_names.map!{|name| name.sub(/\..*/, '')}
65
-
66
- strain_names.each do |str|
67
- ss = Strain.new
68
- ss.name = str
69
- ss.save
70
- end
71
-
72
- strains = Array.new
73
- strain_names.each do |strain_name|
74
- strain = Strain.find_by_name(strain_name) # equivalent to Strain.find.where("strains.name=?", strain_name).first
75
- strains << strain
76
- end
77
-
78
- good_snps = 0
79
- # start parsing snps
80
- while line = f.gets
81
- #puts line
82
- details = line.split("\t")
83
- ref = details[0]
84
- ref_pos = details[1]
85
- ref_base = details[3]
86
- snp_base = details[4]
87
- snp_qual = details [5]
88
- format = details[8].split(":")
89
- gt = format.index("GT")
90
- gq = format.index("GQ")
91
- # dp = format.index("DP")
92
- samples = details[9..-1]
93
-
94
- next if ref_base.size != 1 || snp_base.size != 1 # exclude indels (e.g. G,A in REF)
95
- genotypes = samples.map do |s|
96
- format_values = s.chomp.split(":") # output (e.g.): 0/0 \n 0,255,209 \n 99
97
- format_values[gt] # e.g. 0/0
98
- end
10
+ def find_unqiue_snps(strain_names, out, cuttoff_genotype, cuttoff_snp)
99
11
 
100
- genotypes_qualities = samples.map do |s|
101
- format_values = s.chomp.split(":")
102
- format_values[gq] # e.g. 99
103
- end
12
+ *strain_names = strain_names
104
13
 
105
- geno_quality_array = Array.new
14
+ where_statement = strain_names.collect{|strain_name| "strains.name = '#{strain_name}' OR "}.join("").sub(/ OR $/, "")
106
15
 
107
- high_quality_variant_genotypes = Array.new # this will be filled with the indicies of genotypes that are "1/1" and have a quality >= 30. Reminder: 0/0 is no SNP, 1/1 is SNP.
108
- variant_genotypes = Array.new
109
- genotypes.each_with_index do |gt, index| # indexes each 'genotypes'.
110
- if gt == "1/1"
111
- variant_genotypes << index # variant_genotypes is the position of genome positions that have a correct SNP with 1/1. if you want the total number of strains thats have 1/1 for that row (genome position) then puts variant_genotypes.size
112
- if genotypes_qualities[index].to_i >= cuttoff_genotype.to_i
113
- high_quality_variant_genotypes << index
114
- end
115
- end
116
- end
16
+ outfile = File.open(out, "w")
117
17
 
118
- genotypes_qualities.each do |gq|
119
- if gq.to_i >= cuttoff_genotype.to_i
120
- geno_quality_array << gq
121
- end
122
- end
18
+ snps = Snp.find_by_sql("SELECT snps.* from snps INNER JOIN alleles ON alleles.snp_id = snps.id INNER JOIN genotypes ON alleles.id = genotypes.allele_id INNER JOIN strains ON strains.id = genotypes.strain_id WHERE (#{where_statement}) AND alleles.id <> snps.reference_allele_id AND genotypes.geno_qual >= #{cuttoff_genotype} AND snps.qual >= #{cuttoff_snp} AND (SELECT COUNT(*) from snps AS s INNER JOIN alleles ON alleles.snp_id = snps.id INNER JOIN genotypes ON alleles.id = genotypes.allele_id WHERE alleles.id <> snps.reference_allele_id and s.id = snps.id) = #{strain_names.size} GROUP BY snps.id HAVING COUNT(*) = #{strain_names.size}")
123
19
 
124
- # # high_quality_variant_genotypes is the position of 1/1 and genotype quality above cuttoff_genotype. high_quality_variant_genotypes.size will give you the number of 1/1 in a row (genome position) that is above the genotype quality cuttoff.
125
- # puts "yay" if geno_quality_array.keep_if {|z| z <= cuttoff_genotype.to_i}
20
+ puts "The number of unique snps are #{snps.size}"
126
21
 
127
- # next if geno_quality_array.each {|z| z.to_i < cuttoff_genotype.to_i}
128
- next if samples.include?("./.")
129
- next if geno_quality_array.size != strains.size
130
- if snp_qual.to_i >= cuttoff_snp.to_i && genotypes.include?("1/1") && ! high_quality_variant_genotypes.empty? && high_quality_variant_genotypes.size == variant_genotypes.size
131
- # first condition checks the overall quality of the SNP is >=90, second checks that at least one genome has the 'homozygous' 1/1 variant type with quality >= 30 and informative SNP
132
-
133
- if genotypes.include?("0/0") && !genotypes.include?("0/1") # exclude SNPs which are all 1/1 i.e something strange about ref and those which have confusing heterozygote 0/1s
134
-
135
- good_snps +=1
136
- # puts good_snps
137
- #create snp
138
- s = Snp.new
139
- s.ref_pos = ref_pos
140
- s.qual = snp_qual
141
- s.save
142
-
143
- # create ref allele
144
- ref_allele = Allele.new
145
- ref_allele.base = ref_base
146
- ref_allele.snp = s
147
- ref_allele.save
148
-
149
- s.reference_allele = ref_allele
150
- s.save
151
-
152
- # create snp allele
153
- snp_allele = Allele.new
154
- snp_allele.base = snp_base
155
- snp_allele.snp = s
156
- snp_allele.save
157
-
158
- ActiveRecord::Base.transaction do
159
- genos = []
160
- genotypes.each_with_index do |gt, index|
161
- genotype = Genotype.new
162
- genotype.strain = strains[index]
163
- genotype.geno_qual = genotypes_qualities[index].to_i
164
- puts index if strains[index].nil?
165
- if gt == "0/0" # wild type
166
- genotype.allele = ref_allele
167
- elsif gt == "1/1" # snp type
168
- genotype.allele = snp_allele
169
- else
170
- puts "Strange SNP #{gt}"
171
- end
172
- genos << genotype
173
- end
174
- # Using activerecord-import to speed up importing
175
- Genotype.import genos, :validate => false
176
- puts "Total SNPs added so far: #{good_snps}" if good_snps % 100 == 0
177
- end
178
- end
179
-
180
- end
181
- end
182
- end
183
- end
184
- end
185
- #Here we link the features to snps.
186
- Snp.all.each do |snp|
187
- x = Feature.where("features.start <= ? AND features.end >= ?", snp.ref_pos, snp.ref_pos).first
188
- snp.feature = x
189
- snp.save
190
- end
22
+ output_information_methods(snps, outfile, cuttoff_genotype, cuttoff_snp, false)
191
23
  end
192
24
 
193
- def find_shared_snps(strain_names)
194
- *strain_names = strain_names
195
-
196
- where_statement = strain_names.collect{|strain_name| "strains.name = '#{strain_name}' OR "}.join("").sub(/ OR $/, "")
197
-
198
- Snp.find_by_sql("SELECT * from snps INNER JOIN alleles ON alleles.snp_id = snps.id INNER JOIN genotypes ON alleles.id = genotypes.allele_id INNER JOIN strains ON strains.id = genotypes.strain_id WHERE (#{where_statement}) AND alleles.id <> snps.reference_allele_id AND (SELECT COUNT(*) from snps AS s INNER JOIN alleles ON alleles.snp_id = snps.id INNER JOIN genotypes ON alleles.id = genotypes.allele_id WHERE alleles.id <> snps.reference_allele_id and s.id = snps.id) = #{strain_names.size} GROUP BY snps.id HAVING COUNT(*) = #{strain_names.size}")
199
- end
200
-
201
- def synonymous(sequence_file)
202
-
203
- #Reference Sequence
204
- genome_sequence = Bio::FlatFile.open(Bio::GenBank, sequence_file).next_entry
205
-
206
- #Extract all nucleotide sequence from ORIGIN
207
- all_seqs_original = genome_sequence.seq
208
- ref_bases =[]
209
25
 
210
- strains = Strain.all
26
+ def information(out, cuttoff_genotype, cuttoff_snp)
211
27
 
212
- strains_hash = Hash.new
213
- # create a sequence hash
214
- # hash key is strain_id, loop through strain_id
215
- # create an empty array
216
- strains.each do |strain|
217
- strains_hash[strain.id] = Array.new
218
- end
28
+ puts "outputting SNP info....."
29
+
30
+ strains = Strain.all
219
31
 
220
- variants = Feature.find_by_sql("select distinct features.* from features inner join snps on features.id = snps.feature_id inner join alleles on snps.id = alleles.snp_id inner join genotypes on alleles.id = genotypes.allele_id inner join strains on strains.id = genotypes.strain_id where alleles.id <> snps.reference_allele_id and features.name = 'CDS'")
32
+ snps = Snp.find_by_sql("SELECT distinct snps.* from snps INNER JOIN alleles ON alleles.snp_id = snps.id INNER JOIN genotypes ON alleles.id = genotypes.allele_id INNER JOIN strains ON strains.id = genotypes.strain_id where alleles.id <> snps.reference_allele_id")
221
33
 
222
- puts "start_cds_in_ref\tend_cds_in_ref\tpos_of_SNP_in_ref\tref_base\tSNP_base\tsynonymous or non-synonymous\tamino_acid_original\tamino_acid_change\tpossible_pseudogene?\tchange_in_hydrophobicity_of_AA?\tchange_in_polarisation_of_AA?\tchange_in_size_of_AA?"
34
+ outfile = File.open(out, "w")
223
35
 
36
+ output_information_methods(snps, outfile, cuttoff_genotype, cuttoff_snp, true)
224
37
 
225
- variants.each do |variant|
226
- variant.snps.each do |snp|
227
- snp.alleles.each do |allele|
228
- if allele.id != snp.reference_allele_id
229
- all_seqs_mutated = genome_sequence.seq
230
- mutated_seq_translated = []
231
- original_seq_translated = []
232
- all_seqs_mutated[snp.ref_pos.to_i-1] = allele.base
233
-
234
- mutated_seq = Bio::Sequence.auto(all_seqs_mutated[variant.start-1..variant.end-1])
235
- original_seq = Bio::Sequence.auto(all_seqs_original[variant.start-1..variant.end-1])
236
-
237
- if variant.strand == -1
238
- mutated_seq_translated << mutated_seq.reverse_complement.translate
239
- original_seq_translated << original_seq.reverse_complement.translate
240
-
241
- else
242
- mutated_seq_translated << mutated_seq.translate
243
- original_seq_translated << original_seq.translate
244
-
245
- end
246
-
247
- mutated_seq_translated.zip(original_seq_translated).each do |mut, org|
248
- mutated_seq_translated_clean = mut.gsub(/\*$/,"")
249
- original_seq_translated_clean = org.gsub(/\*$/,"")
250
-
251
- hydrophobic = ["I", "L", "V", "C", "A", "G", "M", "F", "Y", "W", "H", "T"]
252
- non_hydrophobic = ["K", "E", "Q", "D", "N", "S", "P", "B"]
253
-
254
- polar = ["Y", "W", "H", "K", "R", "E", "Q", "D", "N", "S", "P", "B"]
255
- non_polar = ["I", "L", "V", "C", "A", "G", "M", "F", "T"]
256
-
257
- small = ["V","C","A","G","D","N","S","T","P"]
258
- non_small = ["I","L","M","F","Y","W","H","K","R","E","Q"]
259
-
260
- if original_seq_translated_clean == mutated_seq_translated_clean
261
- # if original_seq_translated == mutated_seq_translated
262
- if mutated_seq_translated_clean =~ /\*/
263
- puts "#{variant.start}\t#{variant.end}\t#{snp.ref_pos}\t#{all_seqs_original[snp.ref_pos.to_i-1].upcase}\t#{(allele.base).upcase}\tsynonymous\t\t\tYes"
264
- else
265
- puts "#{variant.start}\t#{variant.end}\t#{snp.ref_pos}\t#{all_seqs_original[snp.ref_pos.to_i-1].upcase}\t#{(allele.base).upcase}\tsynonymous"
266
- end
267
- else
268
-
269
- diffs = Diff::LCS.diff(original_seq_translated_clean, mutated_seq_translated_clean)
270
-
271
- if mutated_seq_translated_clean =~ /\*/
272
- puts "#{variant.start}\t#{variant.end}\t#{snp.ref_pos}\t#{all_seqs_original[snp.ref_pos.to_i-1].upcase}\t#{(allele.base).upcase}\tnon-synonymous\t#{diffs[0][0].element}\t#{diffs[0][1].element}\tYes\t#{'Yes' if (hydrophobic.include? diffs[0][0].element) == (non_hydrophobic.include? diffs[0][1].element)}\t#{'Yes' if (polar.include? diffs[0][0].element) == (non_polar.include? diffs[0][1].element)}\t#{'Yes' if (small.include? diffs[0][0].element) == (non_small.include? diffs[0][1].element)}"
273
- else
274
- puts "#{variant.start}\t#{variant.end}\t#{snp.ref_pos}\t#{all_seqs_original[snp.ref_pos.to_i-1].upcase}\t#{(allele.base).upcase}\tnon-synonymous\t#{diffs[0][0].element}\t#{diffs[0][1].element}\t\t#{'Yes' if (hydrophobic.include? diffs[0][0].element) == (non_hydrophobic.include? diffs[0][1].element)}\t#{'Yes' if (polar.include? diffs[0][0].element) == (non_polar.include? diffs[0][1].element)}\t#{'Yes' if (small.include? diffs[0][0].element) == (non_small.include? diffs[0][1].element)}"
275
- end
276
- end
277
- end
278
-
279
- end
280
- end
281
- end
282
- end
283
-
284
- #Take all SNP positions in ref genome
285
- # snp_positions = Feature.find_by_sql("select snps.ref_pos from features inner join snps on features.id = snps.feature_id inner join alleles on snps.id = alleles.snp_id where alleles.id <> snps.reference_allele_id and features.name = 'CDS'").map{|snp| snp.ref_pos}
286
-
287
- # # Take all SNP nucleotide
288
- # snps = Feature.find_by_sql("select alleles.base from features inner join snps on features.id = snps.feature_id inner join alleles on snps.id = alleles.snp_id where alleles.id <> snps.reference_allele_id and features.name = 'CDS'").map{|allele| allele.base}
289
-
290
- # # Mutate (substitute) the original sequence with the SNPs
291
-
292
- # # Here all_seqs_original are all the nucelotide sequences but with the snps subsituted in them
293
-
294
- # #Get start position of CDS with SNP
295
- # coordinates_start = Feature.find_by_sql("select start from features inner join snps on features.id = snps.feature_id inner join alleles on snps.id = alleles.snp_id where features.name = 'CDS' and alleles.id <> snps.reference_allele_id").map{|feature| feature.start}
296
-
297
- # #Get end position of CDS with SNP
298
- # coordinates_end = Feature.find_by_sql("select end from features inner join snps on features.id = snps.feature_id inner join alleles on snps.id = alleles.snp_id where features.name = 'CDS' and alleles.id <> snps.reference_allele_id").map{|feature| feature.end}
38
+ end
299
39
 
300
-
301
- end
@@ -5,6 +5,5 @@ require 'sqlite3'
5
5
  def establish_connection(db_location)
6
6
  ActiveRecord::Base.establish_connection(
7
7
  :adapter => "sqlite3",
8
- :database => db_location,
9
- )
8
+ :database => db_location)
10
9
  end
data/lib/snp_db_models.rb CHANGED
@@ -6,13 +6,13 @@ class Strain < ActiveRecord::Base
6
6
  end
7
7
 
8
8
  class Feature < ActiveRecord::Base
9
+ has_and_belongs_to_many :snps
9
10
  has_many :annotations
10
- has_many :snps
11
11
  end
12
12
 
13
13
  class Snp < ActiveRecord::Base
14
- belongs_to :feature
15
- has_many :alleles
14
+ has_and_belongs_to_many :features
15
+ has_many :alleles
16
16
  belongs_to :reference_allele, :class_name => "Allele", :foreign_key => "reference_allele_id"
17
17
  end
18
18
 
data/lib/snp_db_schema.rb CHANGED
@@ -1,93 +1,132 @@
1
1
  def db_schema
2
- ActiveRecord::Schema.define do
3
- unless table_exists? :strains
4
- create_table :strains do |t|
5
- t.column :name, :string
6
- t.column :description, :string
2
+ ActiveRecord::Schema.define do
3
+ unless table_exists? :strains
4
+ create_table :strains do |t|
5
+ t.column :name, :string
6
+ t.column :description, :string
7
+ end
7
8
  end
8
- end
9
9
 
10
- unless table_exists? :features
11
- create_table :features do |t|
12
- t.column :name, :string
13
- t.column :sequence, :string
14
- t.column :start, :integer
15
- t.column :end, :integer
16
- t.column :strand, :integer
10
+ unless table_exists? :features_snps
11
+ create_table :features_snps, :id => false do |t|
12
+ t.column :feature_id, :integer, :null => false
13
+ t.column :snp_id, :integer, :null => false
14
+ end
17
15
  end
18
- end
19
16
 
20
- unless table_exists? :snps
21
- create_table :snps do |t|
22
- t.column :feature_id, :integer
23
- t.column :ref_pos, :integer
24
- t.column :qual, :float
25
- t.column :reference_allele_id, :integer
17
+ unless table_exists? :features
18
+ create_table :features do |t|
19
+ t.column :name, :string
20
+ t.column :start, :integer
21
+ t.column :end, :integer
22
+ t.column :strand, :integer
23
+ t.column :sequence, :string
24
+ end
26
25
  end
27
- end
28
26
 
29
- unless table_exists? :alleles
30
- create_table :alleles do |t|
31
- t.column :snp_id, :integer
32
- t.column :base, :string
27
+ unless table_exists? :snps
28
+ create_table :snps do |t|
29
+ t.column :ref_pos, :integer
30
+ t.column :qual, :float
31
+ t.column :reference_allele_id, :integer
32
+ end
33
33
  end
34
- end
35
-
36
- unless table_exists? :genotypes
37
- create_table :genotypes do |t|
38
- t.column :allele_id, :integer
39
- t.column :strain_id, :integer
40
- t.column :geno_qual, :float
41
- end
42
- end
43
34
 
44
- unless table_exists? :annotations
45
- create_table :annotations do |t|
46
- t.column :qualifier, :string
47
- t.column :value, :string
48
- t.column :feature_id, :integer
35
+ unless table_exists? :alleles
36
+ create_table :alleles do |t|
37
+ t.column :snp_id, :integer
38
+ t.column :base, :string
39
+ end
49
40
  end
50
- end
51
41
 
52
- # indices
53
- unless index_exists? :features, :name
54
- add_index :features, :name
55
- end
56
- unless index_exists? :features, :start
57
- add_index :features, :start
58
- end
59
- unless index_exists? :features, :end
60
- add_index :features, :end
61
- end
62
- unless index_exists? :features, :strand
63
- add_index :features, :strand
64
- end
65
- unless index_exists? :snps, :ref_pos
66
- add_index :snps, :ref_pos
67
- end
68
- unless index_exists? :snps, :feature_id
69
- add_index :snps, :feature_id
70
- end
71
- unless index_exists? :snps, :qual
72
- add_index :snps, :qual
73
- end
74
- unless index_exists? :alleles, :snp_id
75
- add_index :alleles, :snp_id
76
- end
77
- unless index_exists? :alleles, :base
78
- add_index :alleles, :base
79
- end
80
- unless index_exists? :genotypes, :allele_id
81
- add_index :genotypes, :allele_id
82
- end
83
- unless index_exists? :genotypes, :strain_id
84
- add_index :genotypes, :strain_id
85
- end
86
- unless index_exists? :genotypes, :geno_qual
87
- add_index :genotypes, :geno_qual
88
- end
89
- unless index_exists? :annotations, :feature_id
90
- add_index :annotations, :feature_id
42
+ unless table_exists? :genotypes
43
+ create_table :genotypes do |t|
44
+ t.column :allele_id, :integer
45
+ t.column :strain_id, :integer
46
+ t.column :geno_qual, :float
47
+ end
48
+ end
49
+
50
+ unless table_exists? :annotations
51
+ create_table :annotations do |t|
52
+ t.column :qualifier, :string
53
+ t.column :value, :string
54
+ t.column :feature_id, :integer
55
+ end
56
+ end
57
+
58
+ # indices
59
+ unless index_exists? :strains, :id
60
+ add_index :strains, :id
61
+ end
62
+ unless index_exists? :strains, :name
63
+ add_index :strains, :name
64
+ end
65
+ unless index_exists? :features, :id
66
+ add_index :features, :id
67
+ end
68
+ unless index_exists? :features, :name
69
+ add_index :features, :name
70
+ end
71
+ unless index_exists? :features, :start
72
+ add_index :features, :start
73
+ end
74
+ unless index_exists? :features, :end
75
+ add_index :features, :end
76
+ end
77
+ unless index_exists? :features, :strand
78
+ add_index :features, :strand
79
+ end
80
+ unless index_exists? :features, :sequence
81
+ add_index :features, :sequence
82
+ end
83
+ unless index_exists? :snps, :id
84
+ add_index :snps, :id
85
+ end
86
+ unless index_exists? :snps, :ref_pos
87
+ add_index :snps, :ref_pos
88
+ end
89
+ unless index_exists? :snps, :qual
90
+ add_index :snps, :qual
91
+ end
92
+ unless index_exists? :snps, :reference_allele_id
93
+ add_index :snps, :reference_allele_id
94
+ end
95
+ unless index_exists? :features_snps, :feature_id
96
+ add_index :features_snps, :feature_id
97
+ end
98
+ unless index_exists? :features_snps, :snp_id
99
+ add_index :features_snps, :snp_id
100
+ end
101
+ unless index_exists? :snps, :qual
102
+ add_index :snps, :qual
103
+ end
104
+ unless index_exists? :alleles, :snp_id
105
+ add_index :alleles, :snp_id
106
+ end
107
+ unless index_exists? :alleles, :base
108
+ add_index :alleles, :base
109
+ end
110
+ unless index_exists? :genotypes, :id
111
+ add_index :genotypes, :id
112
+ end
113
+ unless index_exists? :genotypes, :allele_id
114
+ add_index :genotypes, :allele_id
115
+ end
116
+ unless index_exists? :genotypes, :strain_id
117
+ add_index :genotypes, :strain_id
118
+ end
119
+ unless index_exists? :genotypes, :geno_qual
120
+ add_index :genotypes, :geno_qual
121
+ end
122
+ unless index_exists? :annotations, :feature_id
123
+ add_index :annotations, :feature_id
124
+ end
125
+ unless index_exists? :annotations, :qualifier
126
+ add_index :annotations, :qualifier
127
+ end
128
+ unless index_exists? :annotations, :value
129
+ add_index :annotations, :value
130
+ end
91
131
  end
92
- end
93
132
  end