bio-polyploid-tools 0.5.2 → 0.6.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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/bin/polymarker.rb +44 -15
- data/bin/snp_position_to_polymarker.rb +1 -1
- data/bio-polyploid-tools.gemspec +7 -3
- data/lib/bio/PolyploidTools/SNP.rb +8 -2
- data/lib/bio/PolyploidTools/SNPMutant.rb +85 -0
- data/lib/bio/PolyploidTools/SNPSequence.rb +8 -8
- data/lib/bio/db/primer3.rb +139 -108
- data/test/data/IWGSC_CSS_1AL_scaff_1455974.fa +112 -0
- data/test/data/IWGSC_CSS_1AL_scaff_1455974_aln_contigs.fa +2304 -0
- data/test/data/test_from_mutant.csv +3 -0
- data/test/test_snp_parsing.rb +27 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76d57ca94d667e3aff5324977e57d8b7a5f0d91e
|
4
|
+
data.tar.gz: ccd2fad348fbc8a68927b944adc8e13b7d776edf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99edd393245dc13ebf8b10abab165c86a9e808f5cabfe95fccd6607360383d79c277a84e37c831782412817ac35b82dddde717448510dbd5f89b4e5a268640d9
|
7
|
+
data.tar.gz: c387e7b9a9b8d5c6bbb8e286a2fa71e4ecd92093578e58d04d260f5d8f7ba66f47d03856486c030f91488f39078129b27f600329596faec2183e0c521eaf6785
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/bin/polymarker.rb
CHANGED
@@ -36,6 +36,8 @@ options[:bucket] = 1
|
|
36
36
|
options[:model] = "est2genome"
|
37
37
|
options[:arm_selection] = arm_selection_functions[:arm_selection_embl] ;
|
38
38
|
options[:flanking_size] = 150;
|
39
|
+
options[:variation_free_region] = 0
|
40
|
+
options[:extract_found_contigs] = false
|
39
41
|
options[:primer_3_preferences] = {
|
40
42
|
:primer_product_size_range => "50-150" ,
|
41
43
|
:primer_max_size => 25 ,
|
@@ -60,6 +62,11 @@ OptionParser.new do |opts|
|
|
60
62
|
opts.on("-s", "--snp_list FILE", "File with the list of snps to search from, requires --reference to get the sequence using a position") do |o|
|
61
63
|
options[:snp_list] = o
|
62
64
|
end
|
65
|
+
|
66
|
+
opts.on("-t", "--mutant_list FILE", "File with the list of positions with mutation and the mutation line.\n\
|
67
|
+
requires --reference to get the sequence using a position") do |o|
|
68
|
+
options[:mutant_list] = o
|
69
|
+
end
|
63
70
|
|
64
71
|
opts.on("-r", "--reference FILE", "Fasta file with the sequence for the markers (to complement --snp_list)") do |o|
|
65
72
|
options[:reference] = o
|
@@ -71,9 +78,9 @@ OptionParser.new do |opts|
|
|
71
78
|
|
72
79
|
opts.on("-e", "--exonerate_model MODEL", "Model to be used in exonerate to search for the contigs") do |o|
|
73
80
|
options[:model] = o
|
74
|
-
|
81
|
+
end
|
75
82
|
|
76
|
-
|
83
|
+
opts.on("-a", "--arm_selection arm_selection_embl|arm_selection_morex|arm_selection_first_two", "Function to decide the chromome arm") do |o|
|
77
84
|
options[:arm_selection] = arm_selection_functions[o.to_sym];
|
78
85
|
end
|
79
86
|
|
@@ -81,8 +88,20 @@ OptionParser.new do |opts|
|
|
81
88
|
options[:primer_3_preferences] = Bio::DB::Primer3.read_primer_preferences(o, options[:primer_3_preferences] )
|
82
89
|
end
|
83
90
|
|
91
|
+
opts.on("-v", "--variation_free_region INT", "If present, avoid generating the common primer if there are homoeologous SNPs within the specified distance") do |o|
|
92
|
+
options[:variation_free_region] = o.to_i
|
93
|
+
end
|
94
|
+
|
95
|
+
opts.on("-x", "--extract_found_contigs", "If present, save in a separate file the contigs with matches. Useful to debug.") do |o|
|
96
|
+
options[:extract_found_contigs] = true
|
97
|
+
end
|
98
|
+
|
99
|
+
opts.on("-P", "--primers_to_order")do
|
100
|
+
#TODO: have a string with the tails, optional.
|
101
|
+
options[:primers_to_order] = true
|
102
|
+
end
|
103
|
+
|
84
104
|
|
85
|
-
|
86
105
|
end.parse!
|
87
106
|
|
88
107
|
if options[:primer_3_preferences][:primer_product_size_range]
|
@@ -108,8 +127,9 @@ snp_in="B"
|
|
108
127
|
|
109
128
|
fasta_reference = nil
|
110
129
|
#test_file="/Users/ramirezr/Dropbox/JIC/PrimersToTest/test_primers_nick_and_james_1.csv"
|
111
|
-
test_file=options[:marker_list]
|
130
|
+
test_file=options[:marker_list] if options[:marker_list]
|
112
131
|
test_file=options[:snp_list] if options[:snp_list]
|
132
|
+
test_file=options[:mutant_list] if options[:mutant_list]
|
113
133
|
fasta_reference = options[:reference]
|
114
134
|
output_folder="#{test_file}_primer_design_#{Time.now.strftime('%Y%m%d-%H%M%S')}"
|
115
135
|
output_folder= options[:output_folder] if options[:output_folder]
|
@@ -122,12 +142,12 @@ primer_3_input="#{output_folder}/primer_3_input_temp"
|
|
122
142
|
primer_3_output="#{output_folder}/primer_3_output_temp"
|
123
143
|
exons_filename="#{output_folder}/exons_genes_and_contigs.fa"
|
124
144
|
output_primers="#{output_folder}/primers.csv"
|
145
|
+
output_to_order="#{output_folder}/primers_to_order.csv"
|
125
146
|
@status_file="#{output_folder}/status.txt"
|
126
147
|
|
127
148
|
primer_3_config=File.expand_path(File.dirname(__FILE__) + '/../conf/primer3_config')
|
128
149
|
model=options[:model]
|
129
150
|
|
130
|
-
|
131
151
|
def write_status(status)
|
132
152
|
f=File.open(@status_file, "a")
|
133
153
|
f.puts "#{Time.now.to_s},#{status}"
|
@@ -148,9 +168,6 @@ if fasta_reference
|
|
148
168
|
p "Fasta reference: #{fasta_reference}"
|
149
169
|
end
|
150
170
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
171
|
#1. Read all the SNP files
|
155
172
|
#chromosome = nil
|
156
173
|
write_status "Reading SNPs"
|
@@ -167,13 +184,22 @@ File.open(test_file) do | f |
|
|
167
184
|
region = fasta_reference_db.index.region_for_entry(snp.gene).get_full_region
|
168
185
|
snp.template_sequence = fasta_reference_db.fetch_sequence(region)
|
169
186
|
else
|
170
|
-
|
187
|
+
write_status "WARN: Unable to find entry for #{snp.gene}"
|
188
|
+
end
|
189
|
+
elsif options[:mutant_list] and options[:reference] #List and fasta file
|
190
|
+
snp = Bio::PolyploidTools::SNPMutant.parse(line)
|
191
|
+
entry = fasta_reference_db.index.region_for_entry(snp.contig)
|
192
|
+
if entry
|
193
|
+
region = fasta_reference_db.index.region_for_entry(snp.contig).get_full_region
|
194
|
+
snp.full_sequence = fasta_reference_db.fetch_sequence(region)
|
195
|
+
else
|
196
|
+
write_status "WARN: Unable to find entry for #{snp.gene}"
|
171
197
|
end
|
172
|
-
|
173
198
|
else
|
174
199
|
rise Bio::DB::Exonerate::ExonerateException.new "Wrong number of arguments. "
|
175
200
|
end
|
176
201
|
rise Bio::DB::Exonerate::ExonerateException.new "No SNP for line '#{line}'" if snp == nil
|
202
|
+
|
177
203
|
snp.snp_in = snp_in
|
178
204
|
snp.original_name = original_name
|
179
205
|
if snp.position
|
@@ -206,7 +232,7 @@ file.close
|
|
206
232
|
#chr_group = chromosome[0]
|
207
233
|
write_status "Searching markers in genome"
|
208
234
|
exo_f = File.open(exonerate_file, "w")
|
209
|
-
contigs_f = File.open(temp_contigs, "w")
|
235
|
+
contigs_f = File.open(temp_contigs, "w") if options[:extract_found_contigs]
|
210
236
|
filename=path_to_contigs
|
211
237
|
puts filename
|
212
238
|
target=filename
|
@@ -224,13 +250,13 @@ Bio::DB::Exonerate.align({:query=>temp_fasta_query, :target=>target, :model=>mod
|
|
224
250
|
raise ExonerateException.new, "Entry not found! #{aln.target_id}. Make sure that the #{target_id}.fai was generated properly." if entry == nil
|
225
251
|
region = entry.get_full_region
|
226
252
|
seq = fasta_file.fetch_sequence(region)
|
227
|
-
contigs_f.puts(">#{aln.target_id}\n#{seq}")
|
253
|
+
contigs_f.puts(">#{aln.target_id}\n#{seq}") if options[:extract_found_contigs]
|
228
254
|
end
|
229
255
|
end
|
230
256
|
end
|
231
257
|
|
232
|
-
exo_f.close()
|
233
|
-
contigs_f.close()
|
258
|
+
exo_f.close()
|
259
|
+
contigs_f.close() if options[:extract_found_contigs]
|
234
260
|
|
235
261
|
#4. Load all the results from exonerate and get the input filename for primer3
|
236
262
|
#Custom arm selection function that only uses the first two characters. Maybe
|
@@ -241,12 +267,13 @@ write_status "Reading best alignment on each chromosome"
|
|
241
267
|
container= Bio::PolyploidTools::ExonContainer.new
|
242
268
|
container.flanking_size=options[:flanking_size]
|
243
269
|
container.gene_models(temp_fasta_query)
|
244
|
-
container.chromosomes(
|
270
|
+
container.chromosomes(fasta_reference)
|
245
271
|
container.add_parental({:name=>snp_in})
|
246
272
|
container.add_parental({:name=>original_name})
|
247
273
|
snps.each do |snp|
|
248
274
|
snp.container = container
|
249
275
|
snp.flanking_size = container.flanking_size
|
276
|
+
snp.variation_free_region = options[:variation_free_region]
|
250
277
|
container.add_snp(snp)
|
251
278
|
end
|
252
279
|
container.add_alignments({:exonerate_file=>exonerate_file, :arm_selection=>options[:arm_selection] , :min_identity=>min_identity})
|
@@ -281,6 +308,8 @@ kasp_container.add_primers_file(primer_3_output) if added_exons > 0
|
|
281
308
|
header = "Marker,SNP,RegionSize,chromosome,total_contigs,contig_regions,SNP_type,#{original_name},#{snp_in},common,primer_type,orientation,#{original_name}_TM,#{snp_in}_TM,common_TM,selected_from,product_size,errors"
|
282
309
|
File.open(output_primers, 'w') { |f| f.write("#{header}\n#{kasp_container.print_primers}") }
|
283
310
|
|
311
|
+
File.open(output_to_order, "w") { |io| io.write(kasp_container.print_primers_with_tails()) }
|
312
|
+
|
284
313
|
write_status "DONE"
|
285
314
|
rescue StandardError => e
|
286
315
|
write_status "ERROR\t#{e.message}"
|
@@ -28,7 +28,7 @@ OptionParser.new do |opts|
|
|
28
28
|
|
29
29
|
opts.banner = "Usage: snp_postion_to_polymarker.rb [options]"
|
30
30
|
|
31
|
-
opts.on("-s", "--
|
31
|
+
opts.on("-s", "--snp_file CSV", "CSV file with the following columnns:\nID,Allele_1,position,Allele_1,target_chromosome") do |o|
|
32
32
|
options[:snp_file] = o
|
33
33
|
end
|
34
34
|
opts.on("-r", "--reference FASTA", "reference with the genes/contings/marker seuqnece") do |o|
|
data/bio-polyploid-tools.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: bio-polyploid-tools 0.
|
5
|
+
# stub: bio-polyploid-tools 0.6.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "bio-polyploid-tools"
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.6.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Ricardo H. Ramirez-Gonzalez"]
|
14
|
-
s.date = "
|
14
|
+
s.date = "2015-02-15"
|
15
15
|
s.description = "Repository of tools developed in TGAC and Crop Genetics in JIC to work with polyploid wheat"
|
16
16
|
s.email = "ricardo.ramirez-gonzalez@tgac.ac.uk"
|
17
17
|
s.executables = ["bfr.rb", "count_variations.rb", "filter_blat_by_target_coverage.rb", "find_best_blat_hit.rb", "find_best_exonerate.rb", "hexaploid_primers.rb", "homokaryot_primers.rb", "map_markers_to_contigs.rb", "markers_in_region.rb", "polymarker.rb", "snp_position_to_polymarker.rb", "snps_between_bams.rb"]
|
@@ -81,6 +81,7 @@ Gem::Specification.new do |s|
|
|
81
81
|
"lib/bio/PolyploidTools/Marker.rb",
|
82
82
|
"lib/bio/PolyploidTools/PrimerRegion.rb",
|
83
83
|
"lib/bio/PolyploidTools/SNP.rb",
|
84
|
+
"lib/bio/PolyploidTools/SNPMutant.rb",
|
84
85
|
"lib/bio/PolyploidTools/SNPSequence.rb",
|
85
86
|
"lib/bio/db/exonerate.rb",
|
86
87
|
"lib/bio/db/primer3.rb",
|
@@ -91,6 +92,8 @@ Gem::Specification.new do |s|
|
|
91
92
|
"test/data/BS00068396_51_contigs.fa",
|
92
93
|
"test/data/BS00068396_51_exonerate.tab",
|
93
94
|
"test/data/BS00068396_51_genes.txt",
|
95
|
+
"test/data/IWGSC_CSS_1AL_scaff_1455974.fa",
|
96
|
+
"test/data/IWGSC_CSS_1AL_scaff_1455974_aln_contigs.fa",
|
94
97
|
"test/data/LIB1716.bam",
|
95
98
|
"test/data/LIB1716.bam.bai",
|
96
99
|
"test/data/LIB1719.bam",
|
@@ -111,6 +114,7 @@ Gem::Specification.new do |s|
|
|
111
114
|
"test/data/patological_cases5D.csv",
|
112
115
|
"test/data/primer_3_input_header_test",
|
113
116
|
"test/data/short_primer_design_test.csv",
|
117
|
+
"test/data/test_from_mutant.csv",
|
114
118
|
"test/data/test_iselect.csv",
|
115
119
|
"test/data/test_iselect_reference.fa",
|
116
120
|
"test/data/test_iselect_reference.fa.fai",
|
@@ -14,6 +14,7 @@ module Bio::PolyploidTools
|
|
14
14
|
attr_accessor :genomes_count
|
15
15
|
attr_accessor :primer_3_min_seq_length
|
16
16
|
attr_accessor :chromosome
|
17
|
+
attr_accessor :variation_free_region
|
17
18
|
|
18
19
|
#Format:
|
19
20
|
#Gene_name,Original,SNP_Pos,pos,chromosome
|
@@ -37,6 +38,7 @@ module Bio::PolyploidTools
|
|
37
38
|
def initialize
|
38
39
|
@genomes_count = 3 #TODO: if we want to use this with other polyploids, me need to set this as a variable in the main script.
|
39
40
|
@primer_3_min_seq_length = 50
|
41
|
+
@variation_free_region = 0
|
40
42
|
end
|
41
43
|
|
42
44
|
def to_polymarker_sequence(flanking_size)
|
@@ -260,8 +262,14 @@ module Bio::PolyploidTools
|
|
260
262
|
sequence = reverse_complement_string(sequence)
|
261
263
|
orientation = "reverse"
|
262
264
|
end
|
265
|
+
if @variation_free_region > 0
|
266
|
+
check_str = sequence[right+1, @variation_free_region]
|
267
|
+
return nil if check_str != check_str.downcase
|
268
|
+
end
|
269
|
+
|
263
270
|
end
|
264
271
|
|
272
|
+
|
265
273
|
str = "SEQUENCE_ID=#{opts[:name]} #{orientation}\n"
|
266
274
|
str << "SEQUENCE_FORCE_LEFT_END=#{left}\n"
|
267
275
|
str << "SEQUENCE_FORCE_RIGHT_END=#{right}\n" if opts[:right_pos]
|
@@ -279,8 +287,6 @@ module Bio::PolyploidTools
|
|
279
287
|
str << "SEQUENCE_FORCE_LEFT_END=#{left}\n"
|
280
288
|
str << "SEQUENCE_TEMPLATE=#{sequence}\n"
|
281
289
|
str << "=\n"
|
282
|
-
else
|
283
|
-
|
284
290
|
end
|
285
291
|
|
286
292
|
str
|
@@ -0,0 +1,85 @@
|
|
1
|
+
|
2
|
+
require_relative "SNPSequence"
|
3
|
+
require 'bio-samtools'
|
4
|
+
module Bio::PolyploidTools
|
5
|
+
class SNPSequenceException < RuntimeError
|
6
|
+
end
|
7
|
+
|
8
|
+
class SNPMutant < SNPSequence
|
9
|
+
|
10
|
+
attr_accessor :library, :contig, :chr
|
11
|
+
#Format:
|
12
|
+
#seqid,library,position,wt_base,mut_base
|
13
|
+
#IWGSC_CSS_1AL_scaff_1455974,Kronos2281,127,C,T
|
14
|
+
def self.parse(reg_str)
|
15
|
+
reg_str.chomp!
|
16
|
+
snp = SNPMutant.new
|
17
|
+
|
18
|
+
arr = reg_str.split(",")
|
19
|
+
|
20
|
+
throw SNPSequenceException.new "Need five fields to parse, and got #{arr.size} in #{reg_str}" unless arr.size == 5
|
21
|
+
|
22
|
+
snp.contig, snp.library, snp.position, snp.original, snp.snp = reg_str.split(",")
|
23
|
+
snp.position = snp.position.to_i
|
24
|
+
snp.gene = "EMPTY"
|
25
|
+
begin
|
26
|
+
toks = snp.contig.split('_')
|
27
|
+
#1AL_1455974_Kronos2281_127C
|
28
|
+
#snp.chr = contig.split('_')[2][0,2] #This parses the default from the IWGSC. We may want to make this a lambda
|
29
|
+
#snp.chr = toks[2][0,2]
|
30
|
+
name = toks[2] + "_" + toks[4] + "_" + snp.library + "_" + snp.position.to_s
|
31
|
+
snp.gene = name
|
32
|
+
snp.chromosome = toks[2][0,2]
|
33
|
+
snp.chr = snp.chromosome
|
34
|
+
|
35
|
+
rescue Exception => e
|
36
|
+
$stderr.puts "WARN: snp.chr couldnt be set, the sequence id to parse was #{snp.contig}. We expect something like: IWGSC_CSS_1AL_scaff_1455974"
|
37
|
+
snp.gene = "Error"
|
38
|
+
$stderr.puts e
|
39
|
+
end
|
40
|
+
|
41
|
+
snp.exon_list = Hash.new()
|
42
|
+
snp.flanking_size=100
|
43
|
+
snp
|
44
|
+
end
|
45
|
+
|
46
|
+
def full_sequence=(seq)
|
47
|
+
self.template_sequence = seq
|
48
|
+
self.sequence_original = self.to_polymarker_sequence(self.flanking_size)
|
49
|
+
self.parse_sequence_snp
|
50
|
+
end
|
51
|
+
|
52
|
+
def full_sequence()
|
53
|
+
self.template_sequence
|
54
|
+
end
|
55
|
+
|
56
|
+
def chromosome_group
|
57
|
+
chr[0]
|
58
|
+
end
|
59
|
+
|
60
|
+
def chromosome_genome
|
61
|
+
chr[1]
|
62
|
+
end
|
63
|
+
|
64
|
+
def chromosome_genome
|
65
|
+
return chr[3] if chr[3]
|
66
|
+
return nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def parse_sequence_snp
|
70
|
+
pos = 0
|
71
|
+
match_data = /(?<pre>\w*)\[(?<org>[ACGT])\/(?<snp>[ACGT])\](?<pos>\w*)/.match(sequence_original.strip)
|
72
|
+
if match_data
|
73
|
+
@position = Regexp.last_match(:pre).size + 1
|
74
|
+
@original = Regexp.last_match(:org)
|
75
|
+
@snp = Regexp.last_match(:snp)
|
76
|
+
amb_base = Bio::NucleicAcid.to_IUAPC("#{@original}#{@snp}")
|
77
|
+
@template_sequence = "#{Regexp.last_match(:pre)}#{amb_base}#{Regexp.last_match(:pos)}"
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
@@ -41,14 +41,14 @@ module Bio::PolyploidTools
|
|
41
41
|
pos = 0
|
42
42
|
match_data = /(?<pre>\w*)\[(?<org>[ACGT])\/(?<snp>[ACGT])\](?<pos>\w*)/.match(sequence_original.strip)
|
43
43
|
if match_data
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
44
|
+
@position = Regexp.last_match(:pre).size + 1
|
45
|
+
@original = Regexp.last_match(:org)
|
46
|
+
@snp = Regexp.last_match(:snp)
|
47
|
+
|
48
|
+
amb_base = Bio::NucleicAcid.to_IUAPC("#{@original}#{@snp}")
|
49
|
+
|
50
|
+
@template_sequence = "#{Regexp.last_match(:pre)}#{amb_base}#{Regexp.last_match(:pos)}"
|
51
|
+
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
data/lib/bio/db/primer3.rb
CHANGED
@@ -17,18 +17,18 @@ module Bio::DB::Primer3
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.prepare_input_file(file, opts2={})
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
opts = {
|
21
|
+
:primer_product_size_range => "50-150" ,
|
22
|
+
:primer_max_size => 25 ,
|
23
|
+
:primer_lib_ambiguity_codes_consensus => 1,
|
24
|
+
:primer_liberal_base => 1,
|
25
|
+
:primer_num_return => 5,
|
26
|
+
:primer_explain_flag => 1,
|
27
|
+
:primer_thermodynamic_parameters_path => File.expand_path(File.dirname(__FILE__) + '../../../../conf/primer3_config/') + '/'
|
28
28
|
}.merge(opts2)
|
29
29
|
|
30
30
|
opts.each do |key,value|
|
31
|
-
|
31
|
+
file.puts "#{key.to_s.upcase}=#{value}\n"
|
32
32
|
end
|
33
33
|
# file.puts "="
|
34
34
|
end
|
@@ -68,7 +68,7 @@ module Bio::DB::Primer3
|
|
68
68
|
@primers_line_1 = SortedSet.new
|
69
69
|
@primers_line_2 = SortedSet.new
|
70
70
|
@regions = SortedSet.new
|
71
|
-
|
71
|
+
@primer3_errors = Set.new
|
72
72
|
end
|
73
73
|
|
74
74
|
def line_2_name
|
@@ -106,24 +106,23 @@ module Bio::DB::Primer3
|
|
106
106
|
nil
|
107
107
|
end
|
108
108
|
|
109
|
-
|
110
|
-
|
111
|
-
#TODO: Retrieve error messages
|
109
|
+
def values
|
110
|
+
return @values if @values
|
112
111
|
left_start = 0
|
113
112
|
left_end = 0
|
114
113
|
right_start = 0
|
115
114
|
right_end = 0
|
116
115
|
total_columns_before_messages=17
|
117
|
-
values = Array.new
|
118
|
-
|
119
|
-
values << gene
|
120
|
-
values << "#{original}#{position}#{snp}"
|
121
|
-
values << template_length
|
122
|
-
values << snp_from.chromosome
|
123
|
-
values << regions.size
|
124
|
-
values << regions.join("|")
|
116
|
+
@values = Array.new
|
117
|
+
#@values << "#{gene},,#{template_length},"
|
118
|
+
@values << gene
|
119
|
+
@values << "#{original}#{position}#{snp}"
|
120
|
+
@values << template_length
|
121
|
+
@values << snp_from.chromosome
|
122
|
+
@values << regions.size
|
123
|
+
@values << regions.join("|")
|
125
124
|
if primer3_line_1 and primer3_line_2
|
126
|
-
values << primer3_line_1.polymorphism
|
125
|
+
@values << primer3_line_1.polymorphism
|
127
126
|
|
128
127
|
#Block that searches both if both pairs have a TM
|
129
128
|
primer_2 = primer3_line_2.left_primer_with_coordinates(primer3_line_1.left_coordinates, primer3_line_1.orientation)
|
@@ -133,27 +132,27 @@ module Bio::DB::Primer3
|
|
133
132
|
# $stderr.puts primer_1
|
134
133
|
# $stderr.puts primer_2
|
135
134
|
if primer3_line_1 < primer3_line_2 and primer_2_tm != "NA"
|
136
|
-
values << primer3_line_1.left_primer
|
137
|
-
values << primer_2
|
138
|
-
values << primer3_line_1.right_primer
|
139
|
-
values << primer3_line_1.type.to_s
|
140
|
-
values << primer3_line_1.orientation.to_s
|
141
|
-
values << primer3_line_1.best_pair.left.tm
|
142
|
-
values << primer_2_tm
|
143
|
-
values << primer3_line_1.best_pair.right.tm
|
144
|
-
values << "first"
|
145
|
-
values << primer3_line_1.best_pair.product_size
|
135
|
+
@values << primer3_line_1.left_primer
|
136
|
+
@values << primer_2
|
137
|
+
@values << primer3_line_1.right_primer
|
138
|
+
@values << primer3_line_1.type.to_s
|
139
|
+
@values << primer3_line_1.orientation.to_s
|
140
|
+
@values << primer3_line_1.best_pair.left.tm
|
141
|
+
@values << primer_2_tm
|
142
|
+
@values << primer3_line_1.best_pair.right.tm
|
143
|
+
@values << "first"
|
144
|
+
@values << primer3_line_1.best_pair.product_size
|
146
145
|
elsif primer_1_tm != "NA"
|
147
|
-
values << primer_1
|
148
|
-
values << primer3_line_2.left_primer
|
149
|
-
values << primer3_line_2.right_primer
|
150
|
-
values << primer3_line_2.type.to_s
|
151
|
-
values << primer3_line_2.orientation.to_s
|
152
|
-
values << primer_1_tm
|
153
|
-
values << primer3_line_2.best_pair.left.tm
|
154
|
-
values << primer3_line_2.best_pair.right.tm
|
155
|
-
values << "second"
|
156
|
-
values << primer3_line_2.best_pair.product_size
|
146
|
+
@values << primer_1
|
147
|
+
@values << primer3_line_2.left_primer
|
148
|
+
@values << primer3_line_2.right_primer
|
149
|
+
@values << primer3_line_2.type.to_s
|
150
|
+
@values << primer3_line_2.orientation.to_s
|
151
|
+
@values << primer_1_tm
|
152
|
+
@values << primer3_line_2.best_pair.left.tm
|
153
|
+
@values << primer3_line_2.best_pair.right.tm
|
154
|
+
@values << "second"
|
155
|
+
@values << primer3_line_2.best_pair.product_size
|
157
156
|
else
|
158
157
|
|
159
158
|
first_candidate = find_primer_pair_first
|
@@ -172,80 +171,99 @@ module Bio::DB::Primer3
|
|
172
171
|
|
173
172
|
if first_candidate and second_candidate and first_candidate < second_candidate
|
174
173
|
#puts "A"
|
175
|
-
values << first_candidate.left_primer
|
176
|
-
values << primer_2
|
177
|
-
values << first_candidate.right_primer
|
178
|
-
values << first_candidate.type.to_s
|
179
|
-
values << first_candidate.orientation.to_s
|
180
|
-
values << first_candidate.best_pair.left.tm
|
181
|
-
values << primer_2_tm
|
182
|
-
values << first_candidate.best_pair.right.tm
|
183
|
-
values << "first"
|
184
|
-
values << first_candidate.best_pair.product_size
|
174
|
+
@values << first_candidate.left_primer
|
175
|
+
@values << primer_2
|
176
|
+
@values << first_candidate.right_primer
|
177
|
+
@values << first_candidate.type.to_s
|
178
|
+
@values << first_candidate.orientation.to_s
|
179
|
+
@values << first_candidate.best_pair.left.tm
|
180
|
+
@values << primer_2_tm
|
181
|
+
@values << first_candidate.best_pair.right.tm
|
182
|
+
@values << "first"
|
183
|
+
@values << first_candidate.best_pair.product_size
|
185
184
|
elsif second_candidate
|
186
185
|
#puts "B"
|
187
|
-
values << primer_1
|
188
|
-
values << second_candidate.left_primer
|
189
|
-
values << second_candidate.right_primer
|
190
|
-
values << second_candidate.type.to_s
|
191
|
-
values << second_candidate.orientation.to_s
|
192
|
-
values << primer_1_tm
|
193
|
-
values << second_candidate.best_pair.left.tm
|
194
|
-
values << second_candidate.best_pair.right.tm
|
195
|
-
values << "second"
|
196
|
-
values << second_candidate.best_pair.product_size
|
186
|
+
@values << primer_1
|
187
|
+
@values << second_candidate.left_primer
|
188
|
+
@values << second_candidate.right_primer
|
189
|
+
@values << second_candidate.type.to_s
|
190
|
+
@values << second_candidate.orientation.to_s
|
191
|
+
@values << primer_1_tm
|
192
|
+
@values << second_candidate.best_pair.left.tm
|
193
|
+
@values << second_candidate.best_pair.right.tm
|
194
|
+
@values << "second"
|
195
|
+
@values << second_candidate.best_pair.product_size
|
197
196
|
elsif first_candidate
|
198
197
|
#puts "C"
|
199
|
-
values << first_candidate.left_primer
|
200
|
-
values << primer_2
|
201
|
-
values << first_candidate.right_primer
|
202
|
-
values << first_candidate.type.to_s
|
203
|
-
values << first_candidate.orientation.to_s
|
204
|
-
values << primer_2_tm
|
205
|
-
values << first_candidate.best_pair.left.tm
|
206
|
-
values << first_candidate.best_pair.right.tm
|
207
|
-
values << "first"
|
208
|
-
values << first_candidate.best_pair.product_size
|
209
|
-
# else
|
210
|
-
# values << ""
|
198
|
+
@values << first_candidate.left_primer
|
199
|
+
@values << primer_2
|
200
|
+
@values << first_candidate.right_primer
|
201
|
+
@values << first_candidate.type.to_s
|
202
|
+
@values << first_candidate.orientation.to_s
|
203
|
+
@values << primer_2_tm
|
204
|
+
@values << first_candidate.best_pair.left.tm
|
205
|
+
@values << first_candidate.best_pair.right.tm
|
206
|
+
@values << "first"
|
207
|
+
@values << first_candidate.best_pair.product_size
|
211
208
|
end
|
212
|
-
|
213
209
|
end
|
214
210
|
|
215
211
|
elsif primer3_line_1
|
216
|
-
values << primer3_line_1.polymorphism
|
217
|
-
values << primer3_line_1.left_primer
|
218
|
-
values << primer3_line_1.left_primer_snp(self)
|
219
|
-
values << primer3_line_1.right_primer
|
220
|
-
values << primer3_line_1.type.to_s
|
221
|
-
values << primer3_line_1.orientation.to_s
|
222
|
-
values << primer3_line_1.best_pair.left.tm
|
223
|
-
values << "NA"
|
224
|
-
values << primer3_line_1.best_pair.right.tm
|
225
|
-
|
226
|
-
values << "first+"
|
227
|
-
values << primer3_line_1.best_pair.product_size
|
212
|
+
@values << primer3_line_1.polymorphism
|
213
|
+
@values << primer3_line_1.left_primer
|
214
|
+
@values << primer3_line_1.left_primer_snp(self)
|
215
|
+
@values << primer3_line_1.right_primer
|
216
|
+
@values << primer3_line_1.type.to_s
|
217
|
+
@values << primer3_line_1.orientation.to_s
|
218
|
+
@values << primer3_line_1.best_pair.left.tm
|
219
|
+
@values << "NA"
|
220
|
+
@values << primer3_line_1.best_pair.right.tm
|
221
|
+
|
222
|
+
@values << "first+"
|
223
|
+
@values << primer3_line_1.best_pair.product_size
|
228
224
|
elsif primer3_line_2
|
229
|
-
values << primer3_line_2.polymorphism
|
230
|
-
values << primer3_line_2.left_primer_snp(self)
|
231
|
-
values << primer3_line_2.left_primer
|
232
|
-
values << primer3_line_2.right_primer
|
233
|
-
values << primer3_line_2.type.to_s
|
234
|
-
values << primer3_line_2.orientation.to_s
|
235
|
-
values << "NA"
|
236
|
-
values << primer3_line_2.best_pair.left.tm
|
237
|
-
values << primer3_line_2.best_pair.right.tm
|
238
|
-
values << "second+"
|
239
|
-
values << primer3_line_2.best_pair.product_size
|
225
|
+
@values << primer3_line_2.polymorphism
|
226
|
+
@values << primer3_line_2.left_primer_snp(self)
|
227
|
+
@values << primer3_line_2.left_primer
|
228
|
+
@values << primer3_line_2.right_primer
|
229
|
+
@values << primer3_line_2.type.to_s
|
230
|
+
@values << primer3_line_2.orientation.to_s
|
231
|
+
@values << "NA"
|
232
|
+
@values << primer3_line_2.best_pair.left.tm
|
233
|
+
@values << primer3_line_2.best_pair.right.tm
|
234
|
+
@values << "second+"
|
235
|
+
@values << primer3_line_2.best_pair.product_size
|
240
236
|
|
241
237
|
end
|
242
|
-
if values.size < total_columns_before_messages
|
243
|
-
values[total_columns_before_messages] = primer3_errors.to_a.join("|")
|
238
|
+
if @values.size < total_columns_before_messages
|
239
|
+
@values[total_columns_before_messages] = primer3_errors.to_a.join("|")
|
244
240
|
else
|
245
|
-
values << nil
|
241
|
+
@values << nil
|
246
242
|
end
|
243
|
+
return @values
|
244
|
+
end
|
245
|
+
|
246
|
+
def print_primers
|
247
|
+
self.values.join(",")
|
248
|
+
end
|
249
|
+
|
250
|
+
def found_primers?
|
251
|
+
return self.values[7] && self.values[7] != nil
|
252
|
+
end
|
253
|
+
|
254
|
+
def first_primer
|
255
|
+
return self.values[7] if self.values[7] && self.values[7] != nil
|
256
|
+
return ""
|
257
|
+
end
|
258
|
+
|
259
|
+
def second_primer
|
260
|
+
return self.values[8] if self.values[8] && self.values[8] != nil
|
261
|
+
return ""
|
262
|
+
end
|
247
263
|
|
248
|
-
|
264
|
+
def common_primer
|
265
|
+
return self.values[9] if self.values[9]&& self.values[9] != nil
|
266
|
+
return ""
|
249
267
|
end
|
250
268
|
|
251
269
|
def self.parse(reg_str)
|
@@ -273,10 +291,10 @@ module Bio::DB::Primer3
|
|
273
291
|
def add_record(primer3record)
|
274
292
|
@primer3_errors = Set.new unless @primer3_errors
|
275
293
|
@template_length = primer3record.sequence_template.size
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
294
|
+
if primer3record.primer_error != nil
|
295
|
+
primer3_errors << primer3record.primer_error
|
296
|
+
return
|
297
|
+
end
|
280
298
|
case
|
281
299
|
|
282
300
|
when primer3record.line == @line_1
|
@@ -451,7 +469,7 @@ module Bio::DB::Primer3
|
|
451
469
|
@scores[:chromosome_semispecific] = 100
|
452
470
|
@scores[:chromosome_nonspecific] = 0
|
453
471
|
@scores[:exon] = 50
|
454
|
-
|
472
|
+
|
455
473
|
end
|
456
474
|
|
457
475
|
def snp
|
@@ -654,7 +672,7 @@ module Bio::DB::Primer3
|
|
654
672
|
|
655
673
|
attr_accessor :line_1, :line_2
|
656
674
|
attr_accessor :snp_hash
|
657
|
-
|
675
|
+
|
658
676
|
|
659
677
|
def add_snp_file(filename)
|
660
678
|
@snp_hash=Hash.new unless @snp_hash
|
@@ -696,6 +714,19 @@ module Bio::DB::Primer3
|
|
696
714
|
end
|
697
715
|
return str
|
698
716
|
end
|
717
|
+
|
718
|
+
def print_primers_with_tails(tail_a: "GAAGGTCGGAGTCAACGGATT", tail_b: "GAAGGTGACCAAGTTCATGCT")
|
719
|
+
str = ""
|
720
|
+
snp_hash.each do |k, snp|
|
721
|
+
if snp.found_primers?
|
722
|
+
str << snp.gene << snp.original << "\t" << tail_a << snp.first_primer << "\n"
|
723
|
+
str << snp.gene << snp.snp << "\t" << tail_b << snp.second_primer << "\n"
|
724
|
+
str << snp.gene << "\t" << snp.common_primer << "\n"
|
725
|
+
end
|
726
|
+
end
|
727
|
+
return str
|
728
|
+
end
|
729
|
+
|
699
730
|
end
|
700
731
|
end
|
701
732
|
|