mspire-simulator 0.1.2 → 0.2.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/README.rdoc +46 -3
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/mspire-simulator +8 -0
- data/bin/sim_mail +2 -2
- data/lib/cv_parser.rb +7 -0
- data/lib/ms/curvefit/curve_fit_helper.rb +26 -20
- data/lib/ms/curvefit/mzml_reader.rb +1 -1
- data/lib/ms/curvefit.rb +25 -8
- data/lib/ms/isoelectric_calc.rb +162 -103
- data/lib/ms/merger.rb +46 -33
- data/lib/ms/mzml_wrapper.rb +74 -29
- data/lib/ms/noise.rb +28 -28
- data/lib/ms/rt/rt_helper.rb +3 -3
- data/lib/ms/rt/rtgenerator.rb +63 -51
- data/lib/ms/rt/weka.rb +17 -17
- data/lib/ms/sim_digester.rb +45 -26
- data/lib/ms/sim_feature.rb +180 -122
- data/lib/ms/sim_peptide.rb +58 -55
- data/lib/ms/sim_spectra.rb +22 -23
- data/lib/ms/sim_trollop.rb +36 -32
- data/lib/ms/tr_file_writer.rb +111 -98
- data/lib/progress.rb +21 -20
- data/mspire-simulator.gemspec +5 -5
- data/spec/file_writer_spec.rb +2 -1
- data/spec/merger_spec.rb +2 -1
- data/spec/ms-simulate_spec.rb +1 -1
- data/spec/peptide_spec.rb +2 -1
- data/spec/spec_helper.rb +8 -3
- data/spec/spectra_spec.rb +4 -3
- metadata +5 -5
- data/spec/progress_spec.rb +0 -22
data/README.rdoc
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
=
|
1
|
+
= mspire-simulator
|
2
2
|
|
3
3
|
Description:
|
4
|
-
Simulates MS runs given amino acid
|
4
|
+
Simulates MS runs given amino acid FASTA files. Outputs a .mzML file.
|
5
5
|
|
6
6
|
== Install
|
7
7
|
gem install mspire-simulator
|
@@ -10,8 +10,51 @@ Dependencies:
|
|
10
10
|
weka 3.6.0 - May need to add to CLASSPATH see: http://weka.wikispaces.com/CLASSPATH+problems
|
11
11
|
fftw 3.2.2 - Tested in Linux Mint 12 and Ubuntu Oneiric Ocelot
|
12
12
|
== Examples
|
13
|
-
|
13
|
+
The simplest way to run mspire-simulator is to give it a MZML file
|
14
|
+
with a single centroided elution profile from which, the simulator
|
15
|
+
can extract needed parameters including:
|
16
|
+
- Elution parameters: front, tail, and mu
|
17
|
+
- Overlap range (for merging signals)
|
18
|
+
- Sampling rate
|
19
|
+
- m/z wobble parameters: wobA, wobB
|
20
|
+
- Intensity variance parameters: jagA, jagB, jagC
|
21
|
+
|
22
|
+
$ mspire-simulator --mzml input.mzml [options] <.fasta file>
|
23
|
+
|
24
|
+
Alternatively all parameters can be specified on the command line:
|
25
|
+
|
26
|
+
$ mspire-simulator -r 3000 -s 1.0 -n false ...
|
27
|
+
|
28
|
+
To see all the available options:
|
29
|
+
|
30
|
+
$ mspire-simulator --help
|
31
|
+
|
32
|
+
|
33
|
+
=== Charge State Calculator
|
34
|
+
$ ruby lib/ms/isoelectric_calc.rb --ph 2 --distribution DRVYIHPFHL DRVYIHPF RVYIHPF VYIHPF
|
35
|
+
|
36
|
+
will return:
|
37
|
+
|
38
|
+
DRVYIHPFHL @ pH 2.0: +3, 29.040854; +4, 70.959146
|
39
|
+
|
40
|
+
DRVYIHPF @ pH 2.0: +2, 29.045885; +3, 70.954115
|
41
|
+
|
42
|
+
RVYIHPF @ pH 2.0: +2, 37.364123; +3, 62.635877
|
43
|
+
|
44
|
+
VYIHPF @ pH 2.0: +1, 40.341305; +2, 59.658695
|
45
|
+
|
46
|
+
To see all the available options:
|
47
|
+
$ ruby lib/ms/isoelectric_calc.rb --help
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
== TODO
|
52
|
+
Because of the many options and parameters to specify we will be moving
|
53
|
+
to a .init file format with a .init file editor.
|
54
|
+
|
55
|
+
Other improvments to mspire simulator are also pending.
|
14
56
|
== Copyright
|
15
57
|
|
16
58
|
See LICENSE.txt for further details.
|
17
59
|
|
60
|
+
|
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ require 'jeweler'
|
|
5
5
|
Jeweler::Tasks.new do |gem|
|
6
6
|
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
7
7
|
gem.name = "mspire-simulator"
|
8
|
-
gem.homepage = "
|
8
|
+
gem.homepage = "https://github.com/princelab/mspire-simulator"
|
9
9
|
gem.license = "MIT"
|
10
10
|
gem.summary = %Q{Simulates MS1 runs given amino acid FASTA files. Outputs an MZML file.}
|
11
11
|
gem.description = %Q{Simulates MS1 runs given amino acid FASTA files. Outputs an MZML file.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/bin/mspire-simulator
CHANGED
@@ -19,6 +19,8 @@ require 'ms/sim_digester'
|
|
19
19
|
require 'ms/sim_trollop'
|
20
20
|
require 'ms/merger'
|
21
21
|
|
22
|
+
|
23
|
+
|
22
24
|
module MspireSimulator
|
23
25
|
@opts = MS::Troll.new.get
|
24
26
|
begin
|
@@ -40,6 +42,10 @@ module MspireSimulator
|
|
40
42
|
|
41
43
|
module_function
|
42
44
|
def opts; @opts end
|
45
|
+
|
46
|
+
|
47
|
+
SampleLoad = 1.0 # Instrument dependent scaling, for an Orbitrap, assumed to be 1 ug
|
48
|
+
# TODO define an option for sample loading, and a scaling function to define the peak intensities
|
43
49
|
|
44
50
|
#------------------------Digest-----------------------------------------------
|
45
51
|
peptides = []
|
@@ -80,10 +86,12 @@ module MspireSimulator
|
|
80
86
|
#-----------------------------------------------------------------------------
|
81
87
|
|
82
88
|
|
89
|
+
|
83
90
|
#-----------------------Merge Finish------------------------------------------
|
84
91
|
spectra.spectra = Merger.compact(spectra.spectra)
|
85
92
|
#-----------------------------------------------------------------------------
|
86
93
|
|
94
|
+
|
87
95
|
|
88
96
|
#-----------------------Clean UP----------------------------------------------
|
89
97
|
spectra.features.each{|fe| fe.delete}
|
data/bin/sim_mail
CHANGED
@@ -18,9 +18,9 @@ begin
|
|
18
18
|
:password => 'chromatography',
|
19
19
|
:authentication => :plain,
|
20
20
|
:domain => "localhost.localdomain"
|
21
|
-
|
21
|
+
},
|
22
22
|
:subject => 'Mspire-Simulator', :body => msgbody
|
23
|
-
|
23
|
+
)
|
24
24
|
rescue
|
25
25
|
puts "Email function failed. Check email address and internet connection."
|
26
26
|
end
|
data/lib/cv_parser.rb
ADDED
@@ -35,10 +35,10 @@ class GenCurvefit
|
|
35
35
|
init_population
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
attr_reader :function, :paramsize, :mutation_limits, :population, :generations, :popsize
|
40
40
|
attr_writer :paramsize, :mutation_limits, :population, :generations, :popsize
|
41
|
-
|
41
|
+
|
42
42
|
def init_population
|
43
43
|
@popsize.times do
|
44
44
|
set = []
|
@@ -50,24 +50,24 @@ class GenCurvefit
|
|
50
50
|
@population<<set
|
51
51
|
end
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
def set_fit_function(func)
|
55
55
|
@function = func
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
def mutate(set)
|
59
59
|
index = rand(set.size-1)
|
60
60
|
limits = @mutation_limits[index]
|
61
61
|
set[index] += random_float(limits[0],limits[1])
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
def self.smoothave(arr)
|
65
65
|
smooth_ave = [nil,nil,nil]
|
66
66
|
queue = []
|
67
67
|
arr.each do |i|
|
68
68
|
queue.push(i)
|
69
69
|
if queue.size > 7
|
70
|
-
|
70
|
+
queue.shift
|
71
71
|
end
|
72
72
|
smooth_ave<<queue.inject(:+)/queue.size if queue.size == 7
|
73
73
|
end
|
@@ -76,16 +76,16 @@ class GenCurvefit
|
|
76
76
|
end
|
77
77
|
return smooth_ave
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
def self.normalize(arr)
|
81
81
|
max = arr.max
|
82
82
|
arr.map!{|i| (i.to_f/max) * 100}
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
def sort_by_fitness
|
86
86
|
@population.sort_by!{|set| set.last}
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
def random_float(a,b)
|
90
90
|
a = a.to_f
|
91
91
|
b = b.to_f
|
@@ -94,15 +94,15 @@ class GenCurvefit
|
|
94
94
|
r = random * diff
|
95
95
|
return a + r
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
def rmsd(v,w)
|
99
99
|
n = v.size
|
100
100
|
sum = 0.0
|
101
101
|
n.times{|i| sum += ((v[i][0]-w[i][0])**2.0 + (v[i][1]-w[i][1])**2.0) }
|
102
102
|
return Math.sqrt( (1/n.to_f) * sum )
|
103
103
|
end
|
104
|
-
|
105
|
-
|
104
|
+
|
105
|
+
|
106
106
|
def fitness(set,pts_in,plot = false)
|
107
107
|
pts = []
|
108
108
|
xs = pts_in.transpose[0]
|
@@ -110,18 +110,24 @@ class GenCurvefit
|
|
110
110
|
fit_pt = function.call(set,x)
|
111
111
|
pts<<[x,fit_pt]
|
112
112
|
end
|
113
|
-
|
113
|
+
|
114
114
|
if plot
|
115
115
|
return pts
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
return rmsd(pts_in,pts)
|
119
119
|
end
|
120
|
-
|
120
|
+
|
121
121
|
def fit
|
122
|
-
|
122
|
+
prog = Progress.new("Generation")
|
123
|
+
num = 0
|
124
|
+
total = @generations
|
125
|
+
step = total/100
|
123
126
|
@generations.times do |i|
|
124
|
-
|
127
|
+
if i > step * (num + 1)
|
128
|
+
num = ((i/total.to_f)*100).to_i
|
129
|
+
prog.update(num," #{i+1}:")
|
130
|
+
end
|
125
131
|
#Generate mutations
|
126
132
|
index = rand(@popsize)
|
127
133
|
clone = @population[index].clone
|
@@ -139,14 +145,14 @@ class GenCurvefit
|
|
139
145
|
@best = @population.first
|
140
146
|
end
|
141
147
|
end
|
142
|
-
|
148
|
+
prog.finish!
|
143
149
|
return @best
|
144
150
|
end
|
145
|
-
|
151
|
+
|
146
152
|
def plot(file,labels = nil)
|
147
153
|
pts = fitness(@best,@pts_in,true)
|
148
154
|
Fit_plot.plot(@pts_in,pts,file,labels)
|
149
155
|
puts " Output File: #{file}"
|
150
156
|
end
|
151
|
-
|
157
|
+
|
152
158
|
end
|
data/lib/ms/curvefit.rb
CHANGED
@@ -1,12 +1,15 @@
|
|
1
|
-
|
1
|
+
require 'progress'
|
2
2
|
require 'ms/curvefit/mzml_reader'
|
3
3
|
require 'ms/curvefit/curve_fit_helper'
|
4
4
|
|
5
|
+
@@avg_mz = 0
|
6
|
+
@@avg_rt = 0
|
7
|
+
|
5
8
|
class CurveFit
|
6
9
|
def self.get_parameters(opts)
|
7
10
|
data = Mzml_reader.get_data(opts[:mzml])
|
8
11
|
generations = opts[:generations]
|
9
|
-
|
12
|
+
|
10
13
|
@pts_int_var = []
|
11
14
|
@pts_mz_var = []
|
12
15
|
@pts_elut = []
|
@@ -17,13 +20,16 @@ class CurveFit
|
|
17
20
|
rts_in = data[1]
|
18
21
|
ints_in = data[2]
|
19
22
|
|
23
|
+
@@avg_mz = mzs_in.inject(:+)/mzs_in.size.to_f
|
24
|
+
@@avg_rt = rts_in.inject(:+)/rts_in.size.to_f
|
25
|
+
|
20
26
|
ints_in = GenCurvefit.normalize(ints_in)
|
21
27
|
#-----------------------overlapRange--------------------------------------------
|
22
28
|
mean = mzs_in.inject(:+)/mzs_in.size
|
23
29
|
opts[:overlapRange] = (mzs_in.sample_variance(mean)*10**6)/4
|
24
30
|
#-------------------------------------------------------------------------------
|
25
|
-
|
26
|
-
|
31
|
+
|
32
|
+
|
27
33
|
#----------------------create points/curve to fit elution-----------------------
|
28
34
|
ints_in.each_with_index do |s,i|
|
29
35
|
@pts_elut<<[rts_in[i],s]
|
@@ -46,8 +52,8 @@ class CurveFit
|
|
46
52
|
labels = ["retention time","normalized intensity"]
|
47
53
|
a_fit.plot("elution_curvefit.svg",labels)
|
48
54
|
#-------------------------------------------------------------------------------
|
49
|
-
|
50
|
-
|
55
|
+
|
56
|
+
|
51
57
|
#-----------------create points/curve to fit m/z variance-----------------------
|
52
58
|
wobs = []
|
53
59
|
mean = mzs_in.inject(:+)/mzs_in.size
|
@@ -77,7 +83,7 @@ class CurveFit
|
|
77
83
|
labels = ["normalized intensity","m/z variance"]
|
78
84
|
b_fit.plot("mz_var_curvefit.svg",labels)
|
79
85
|
#-------------------------------------------------------------------------------
|
80
|
-
|
86
|
+
|
81
87
|
#--------------------create points/curve to fit intensity variance--------------
|
82
88
|
smooth_ave = GenCurvefit.smoothave(ints_in)
|
83
89
|
|
@@ -114,7 +120,18 @@ class CurveFit
|
|
114
120
|
labels = ["normalized intensity","intensity variance"]
|
115
121
|
c_fit.plot("intensity_var_curvefit.svg",labels)
|
116
122
|
#-------------------------------------------------------------------------------
|
117
|
-
|
123
|
+
|
118
124
|
return opts
|
119
125
|
end
|
120
126
|
end
|
127
|
+
=begin
|
128
|
+
out_file = File.open("mzvar_params.txt","w")
|
129
|
+
out_file.puts "wobA\twobB\tavg_mz\tavg_rt"
|
130
|
+
ARGV.each do |file|
|
131
|
+
p file
|
132
|
+
opts = {:mzml => file, :generations => 30000}
|
133
|
+
opts = CurveFit.get_parameters(opts)
|
134
|
+
out_file.puts "#{opts[:wobA]}\t#{opts[:wobB]}\t#{@@avg_mz}\t#{@@avg_rt}"
|
135
|
+
end
|
136
|
+
out_file.close
|
137
|
+
=end
|
data/lib/ms/isoelectric_calc.rb
CHANGED
@@ -4,119 +4,178 @@
|
|
4
4
|
|
5
5
|
Precision = 0.001
|
6
6
|
ResidueTable = {
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
# These are the fringe cases... B and Z... Jerks, these are harder to calculate pIs
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
7
|
+
:K => [2.18,8.95,10.53],
|
8
|
+
:E => [2.19,9.67,4.25],
|
9
|
+
:D => [1.88,9.60,3.65],
|
10
|
+
:H => [1.82,9.17,6.00],
|
11
|
+
:R => [2.17,9.04,12.48],
|
12
|
+
:Q => [2.17,9.13,nil],
|
13
|
+
:N => [2.02,8.80,nil],
|
14
|
+
:C => [1.96,10.28,8.18],
|
15
|
+
:T => [2.11,9.62,nil],
|
16
|
+
:S => [2.21,9.15,nil],
|
17
|
+
:W => [2.38,9.39,nil],
|
18
|
+
:Y => [2.20,9.11,10.07],
|
19
|
+
:F => [1.83,9.13,nil],
|
20
|
+
:M => [2.28,9.21,nil],
|
21
|
+
:I => [2.36,9.68,nil],
|
22
|
+
:L => [2.36,9.60,nil],
|
23
|
+
:V => [2.32,9.62,nil],
|
24
|
+
:P => [1.99,10.96,nil],
|
25
|
+
:A => [2.34,9.69,nil],
|
26
|
+
:G => [2.34,9.60,nil],
|
27
|
+
# These are the fringe cases... B and Z... Jerks, these are harder to calculate pIs
|
28
|
+
:B => [1.95,9.20,3.65],
|
29
|
+
:Z => [2.18,9.40,4.25],
|
30
|
+
:X => [2.20,9.40,nil],
|
31
|
+
:U => [1.96,10.28,5.20] # Unfortunately, I've only found the pKr for this... so I've used Cysteine's values.
|
32
32
|
}
|
33
33
|
PepCharges = Struct.new(:seq, :n_term, :c_term, :y_num, :c_num, :k_num, :h_num, :r_num, :d_num, :e_num, :u_num, :polar_num, :hydrophobic_num, :pi)
|
34
34
|
def identify_potential_charges(str)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
35
|
+
string = str.upcase
|
36
|
+
first = string[0]; last = string[-1]
|
37
|
+
puts string if first.nil? or last.nil?
|
38
|
+
begin
|
39
|
+
out = PepCharges.new(string, ResidueTable[first.to_sym][0], ResidueTable[last.to_sym][1], 0, 0, 0 ,0 ,0 ,0, 0, 0, 0, 0, 0)
|
40
|
+
rescue NoMethodError
|
41
|
+
abort string
|
42
|
+
end
|
43
|
+
string.chars.each do |letter|
|
44
|
+
case letter
|
45
|
+
when "Y"
|
46
|
+
out.y_num += 1
|
47
|
+
when "C"
|
48
|
+
out.c_num += 1
|
49
|
+
when "K"
|
50
|
+
out.k_num += 1
|
51
|
+
when "H"
|
52
|
+
out.h_num += 1
|
53
|
+
when "R"
|
54
|
+
out.r_num += 1
|
55
|
+
when "D"
|
56
|
+
out.d_num += 1
|
57
|
+
when "E"
|
58
|
+
out.e_num += 1
|
59
|
+
when "U"
|
60
|
+
out.u_num += 1
|
61
|
+
when "S", "T", "N", "Q"
|
62
|
+
out.polar_num += 1
|
63
|
+
when "A", "V", "I", "L", "M", "F", "W", "G", "P"
|
64
|
+
out.hydrophobic_num += 1
|
65
|
+
end
|
66
|
+
end
|
67
|
+
out
|
68
68
|
end # Returns the PepCharges structure
|
69
69
|
|
70
70
|
def charge_at_pH(pep_charges, pH)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
71
|
+
charge = 0
|
72
|
+
charge += -1/(1+10**(pep_charges.c_term-pH))
|
73
|
+
charge += -pep_charges.d_num/(1+10**(ResidueTable[:D][2]-pH))
|
74
|
+
charge += -pep_charges.e_num/(1+10**(ResidueTable[:E][2]-pH))
|
75
|
+
charge += -pep_charges.c_num/(1+10**(ResidueTable[:C][2]-pH))
|
76
|
+
charge += -pep_charges.y_num/(1+10**(ResidueTable[:Y][2]-pH))
|
77
|
+
charge += 1/(1+10**(pH - pep_charges.n_term))
|
78
|
+
charge += pep_charges.h_num/(1+10**(pH-ResidueTable[:H][2]))
|
79
|
+
charge += pep_charges.k_num/(1+10**(pH-ResidueTable[:K][2]))
|
80
|
+
charge += pep_charges.r_num/(1+10**(pH-ResidueTable[:R][2]))
|
81
|
+
charge
|
82
82
|
end
|
83
83
|
|
84
84
|
|
85
85
|
def calc_PI(pep_charges)
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
86
|
+
pH = 8; pH_prev = 0.0; pH_next = 14.0
|
87
|
+
charge = charge_at_pH(pep_charges, pH)
|
88
|
+
while pH-pH_prev > Precision and pH_next-pH > Precision
|
89
|
+
if charge < 0.0
|
90
|
+
tmp = pH
|
91
|
+
pH = pH - ((pH-pH_prev)/2)
|
92
|
+
charge = charge_at_pH(pep_charges, pH)
|
93
|
+
pH_next = tmp
|
94
|
+
else
|
95
|
+
tmp = pH
|
96
|
+
pH = pH + ((pH_next - pH)/2)
|
97
|
+
charge = charge_at_pH(pep_charges, pH)
|
98
|
+
pH_prev = tmp
|
99
|
+
end
|
100
|
+
# puts "charge: #{charge.round(2)}\tpH: #{pH.round(2)}\tpH_next: #{pH_next.round(2)}\tpH_prev: #{pH_prev.round(2)}"
|
101
|
+
end
|
102
|
+
pH
|
103
103
|
end
|
104
|
-
|
105
|
-
=
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
=
|
113
|
-
=
|
114
|
-
|
115
|
-
|
116
|
-
|
104
|
+
def distribution_from_charge(charge, normalization=100)
|
105
|
+
threshold = normalization.to_f
|
106
|
+
f = charge.floor
|
107
|
+
c = charge.ceil
|
108
|
+
charge_ratio = charge - f
|
109
|
+
num = charge_ratio*normalization
|
110
|
+
denom = normalization
|
111
|
+
while num + denom > threshold
|
112
|
+
factor = threshold/(num+denom)
|
113
|
+
num = num * factor
|
114
|
+
denom = denom * factor
|
115
|
+
end
|
116
|
+
[["+#{f}" + ", " + "%5f" % num],["+#{c}" + ", " + "%5f" % denom]]
|
117
117
|
end
|
118
|
-
=end
|
119
|
-
#out_pi = pepcharges.map {|a| calc_PI(a)}
|
120
118
|
|
121
|
-
|
122
|
-
#
|
119
|
+
|
120
|
+
#pepcharges =[]
|
121
|
+
if $0 == __FILE__
|
122
|
+
VERBOSE = false
|
123
|
+
def putsv(object)
|
124
|
+
puts object if VERBOSE
|
125
|
+
end
|
126
|
+
def out(line, object)
|
127
|
+
line + ":\t" + object.to_s
|
128
|
+
end
|
129
|
+
require 'optparse'
|
130
|
+
|
131
|
+
options = {pi: true, distribution: false, ph: 7.0}
|
132
|
+
parser = OptionParser.new do |opts|
|
133
|
+
opts.banner = "Takes strings and outputs the PI, or charge distribution"
|
134
|
+
|
135
|
+
opts.on('-h','--help', "Displays this help message") do |h|
|
136
|
+
puts opts
|
137
|
+
exit
|
138
|
+
end
|
139
|
+
opts.on('-v','--verbose') {|v| VERBOSE = v}
|
140
|
+
opts.on("--[no]-pi", "Turns on (default) or off the pI output") do |p|
|
141
|
+
options[:pi] = p
|
142
|
+
end
|
143
|
+
opts.on("-d", "--distribution", "Output a string representation of the charge state distribution array") do |d|
|
144
|
+
options[:distribution] = true
|
145
|
+
options[:pi] = false
|
146
|
+
end
|
147
|
+
opts.on('--pH N', Float, "Takes a float value representing a pH at which to make the distribution. DEFAULT: 7.0") do |ph|
|
148
|
+
options[:ph] = ph
|
149
|
+
end
|
150
|
+
opts.on('-f', "--file FILENAME", String, "Takes an input file for parsing") do |f|
|
151
|
+
options[:in_file] = f
|
152
|
+
end
|
153
|
+
end
|
154
|
+
parser.parse!
|
155
|
+
|
156
|
+
# RUN
|
157
|
+
pi = []
|
158
|
+
lines = []
|
159
|
+
if options[:in_file]
|
160
|
+
file_lines = File.readlines(options[:in_file]).map(&:chomp)
|
161
|
+
lines = file_lines.map {|line| line[/^([A-Z]+).*/] }.compact
|
162
|
+
outfile = File.join(File.dirname(options[:in_file]), 'pi_output_file.txt')
|
163
|
+
outputter = File.open(outfile,'w')
|
164
|
+
else
|
165
|
+
lines = ARGV
|
166
|
+
outputter = STDOUT
|
167
|
+
end
|
168
|
+
if options[:pi]
|
169
|
+
lines.each {|line| outputter.puts out(line, calc_PI(identify_potential_charges(line)) ) }
|
170
|
+
elsif options[:distribution]
|
171
|
+
lines.each do |line|
|
172
|
+
charge = charge_at_pH(identify_potential_charges(line), options[:ph])
|
173
|
+
charge_dist = distribution_from_charge(charge)
|
174
|
+
outputter.puts out(line + " @ pH #{options[:ph]}", charge_dist.join("; "))
|
175
|
+
end
|
176
|
+
end
|
177
|
+
if outfile
|
178
|
+
outputter.close
|
179
|
+
puts "OUTPUT in #{outfile}"
|
180
|
+
end
|
181
|
+
end
|