mspire 0.6.24 → 0.6.25

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.24
1
+ 0.6.25
@@ -0,0 +1,105 @@
1
+
2
+ require 'ms/mass'
3
+ require 'ms/isotope'
4
+ require 'ms/molecular_formula'
5
+ require 'ms/spectrum'
6
+
7
+ require 'fftw3'
8
+
9
+ module MS
10
+ class Isotope
11
+ module Distribution
12
+ NORMALIZE = :total
13
+ PERCENT_CUTOFF = 0.001
14
+ end
15
+ end
16
+ end
17
+
18
+ module MS
19
+ class MolecularFormula < Hash
20
+
21
+ # takes any element composition (see any_to_num_elements).
22
+ #
23
+ # returns isotopic distribution beginning with monoisotopic peak and
24
+ # finishing when the peak contributes less than percent_cutoff to the total
25
+ # distribution. Then, normalization occurs.
26
+ #
27
+ # all values will be fractional. normalize may be one of:
28
+ #
29
+ # :total normalize to the total intensity
30
+ # :max normalize to the highest peak intensity
31
+ # :low normalize to the intensity of the lowest m/z peak
32
+ # (this is typically the monoisotopic peak)
33
+ def isotope_distribution(normalize=MS::Isotope::Distribution::NORMALIZE, percent_cutoff=MS::Isotope::Distribution::PERCENT_CUTOFF)
34
+ mono_dist = raw_isotope_distribution
35
+ # percent_cutoff:
36
+ final_output = []
37
+ sum = 0.0
38
+ mono_dist.each do |peak|
39
+ break if (peak / sum)*100 < percent_cutoff
40
+ final_output << peak
41
+ sum += peak
42
+ end
43
+
44
+ # normalization
45
+ norm_by =
46
+ case normalize
47
+ when :total
48
+ sum
49
+ when :max
50
+ final_output.max
51
+ when :low
52
+ final_output.first
53
+ end
54
+ final_output.map {|i| i / norm_by }
55
+ end
56
+
57
+ # returns a spectrum object with mass values and intensity values.
58
+ # Arguments are passed directly to isotope_distribution.
59
+ def isotope_distribution_spectrum(*args)
60
+ intensities = isotope_distribution(*args)
61
+ mono = self.map {|el,cnt| MS::Mass::MONO[el]*cnt }.reduce(:+)
62
+ masses = Array.new(intensities.size)
63
+ neutron = MS::Mass::NEUTRON
64
+ masses[0] = mono
65
+ (1...masses.size).each {|i| masses[i] = masses[i-1] + neutron }
66
+ MS::Spectrum.new [masses, intensities]
67
+ end
68
+
69
+ # returns relative ratios from low nominal mass to high nominal mass.
70
+ # These are *not* normalized at all.
71
+ def raw_isotope_distribution
72
+ low_nominal = 0
73
+ high_nominal = 0
74
+ self.each do |el,cnt|
75
+ isotopes = MS::Isotope::BY_ELEMENT[el]
76
+ low_nominal += (isotopes.first.mass_number * cnt)
77
+ high_nominal += (isotopes.last.mass_number * cnt)
78
+ end
79
+
80
+ ffts = self.map do |el, cnt|
81
+ isotope_el_ar = NArray.float(high_nominal)
82
+ MS::Isotope::BY_ELEMENT[el].each do |isotope|
83
+ isotope_el_ar[isotope.mass_number] = isotope.relative_abundance
84
+ end
85
+ FFTW3.fft(isotope_el_ar)**cnt
86
+ end
87
+ FFTW3.ifft(ffts.reduce(:*)).real.to_a[low_nominal..high_nominal]
88
+ end
89
+
90
+ end
91
+
92
+
93
+ class Isotope
94
+ module Distribution
95
+ def self.calculate(molecular_formula_like, normalize=MS::Isotope::Distribution::NORMALIZE, percent_cutoff=MS::Isotope::Distribution::PERCENT_CUTOFF)
96
+ MS::MolecularFormula.new(molecular_formula_like).isotope_distribution(normalize, percent_cutoff)
97
+ end
98
+
99
+ def self.spectrum(molecular_formula_like, normalize=MS::Isotope::Distribution::NORMALIZE, percent_cutoff=MS::Isotope::Distribution::PERCENT_CUTOFF)
100
+ MS::MolecularFormula.new(molecular_formula_like).isotope_distribution_spectrum(normalize, percent_cutoff)
101
+ end
102
+ end
103
+ end
104
+
105
+ end
data/lib/ms/mass.rb CHANGED
@@ -1,56 +1,50 @@
1
+ require 'ms/isotope'
2
+ require 'ms/molecular_formula'
3
+
1
4
  module MS
2
5
  module Mass
3
6
 
4
7
  # takes a molecular formula in this format: C2BrH12O
5
8
  def self.formula_to_exact_mass(formula)
6
- # TODO: add other input methods
7
- pairs = formula.scan(/([A-Z][a-z]?)(\d*)/).map do |match|
8
- if match.last == ''
9
- match[-1] = 1
10
- end
11
- [match[0], match[1].to_i]
12
- end
13
- pairs.map do |pair|
14
- MONO[pair.first.downcase] * pair.last
9
+ MS::MolecularFormula.new(formula).map do |el,cnt|
10
+ MONO[el] * cnt
15
11
  end.reduce(:+)
16
12
  end
17
13
 
18
- ELECTRON = 0.0005486 # www.mikeblaber.org/oldwine/chm1045/notes/Atoms/.../Atoms03.htm
19
- H_PLUS = 1.00727646677
20
- # + http://www.unimod.org/masses.html
21
14
  MONO_STR = {
22
- 'c' => 12.0, # +
23
- 'br' => 78.9183361, # +
24
- 'd' => 2.014101779, # +
25
- 'f' => 18.99840322, # +
26
- 'n' => 14.003074, # +
27
- 'o' => 15.99491463, # +
28
- 'na' => 22.9897677, # +
29
- 'p' => 30.973762, # +
30
- 's' => 31.9720707, # +
31
- 'li' => 7.016003, # +
32
- 'cl' => 34.96885272, # +
33
- 'k' => 38.9637074, # +
34
- 'si' => 27.9769265325, # http://physics.nist.gov/cgi-bin/Compositions/stand_alone.pl?ele=Si&ascii=html&isotype=some
35
- 'i' => 126.904473, # +
36
15
  'h+' => 1.00727646677,
37
- 'h' => 1.007825035, # +
38
- 'h2o' => 18.0105647,
39
- 'oh' => 17.002739665,
40
- 'e' => 0.0005486,
41
- 'se' => 79.9165196
16
+ 'e' => 0.0005486, # www.mikeblaber.org/oldwine/chm1045/notes/Atoms/.../Atoms03.htm
17
+ 'neutron' => 1.0086649156,
42
18
  }
19
+ MS::Isotope::BY_ELEMENT.each do |el, isotopes|
20
+ MONO_STR[el.to_s] = isotopes.find {|iso| iso.mono }.atomic_mass
21
+ end
22
+ MONO_STR['h2o'] = %w(h h o).map {|el| MONO_STR[el] }.reduce(:+)
23
+ MONO_STR['oh'] = %w(o h).map {|el| MONO_STR[el] }.reduce(:+)
24
+ # add on deuterium
25
+ MONO_STR['d'] = MS::Isotope::BY_ELEMENT[:h].find {|iso| iso.element == :h && iso.mass_number == 2 }.atomic_mass
26
+
43
27
  AVG_STR = {
44
28
  'h+' => 1.007276, # using Mascot_H_plus mass (is this right for AVG??)
45
- 'h' => 1.00794,
46
- 'h2o' => 18.01528,
47
- 'oh' => 17.00734,
29
+ 'e' => 0.0005486,
30
+ 'neutron' => 1.0086649156,
48
31
  }
49
- # sets MONO_STR, MONO, AVG_STR, and AVG
32
+ MS::Isotope::BY_ELEMENT.each do |el, isotopes|
33
+ AVG_STR[el.to_s] = isotopes.first.average_mass
34
+ end
35
+ AVG_STR['h2o'] = %w(h h o).map {|el| AVG_STR[el] }.reduce(:+)
36
+ AVG_STR['oh'] = %w(o h).map {|el| AVG_STR[el] }.reduce(:+)
37
+
38
+ # sets MONO_SYM, MONO, AVG_SYM, and AVG
50
39
  %w(MONO AVG).each do |type|
51
40
  const_set "#{type}_SYM", Hash[ const_get("#{type}_STR").map {|k,v| [k.to_sym, v] } ]
52
41
  const_set type, const_get("#{type}_STR").merge( const_get("#{type}_SYM") )
53
42
  end
43
+
44
+ ELECTRON = MONO[:e]
45
+ NEUTRON = MONO[:neutron]
46
+ H_PLUS = MONO['h+']
47
+
54
48
  end
55
49
  end
56
50
 
@@ -0,0 +1,21 @@
1
+ require 'ms/isotope'
2
+
3
+ module MS
4
+ class MolecularFormula < Hash
5
+
6
+ # takes a string or a hash:
7
+ #
8
+ # "H22C12N1O3S2BeLi2" # <= order doesn't matter
9
+ # {h: 22, c: 12, n: 1, o: 3, s: 2} # case and string/sym doesn't matter
10
+ def initialize(arg)
11
+ if arg.is_a?(String)
12
+ arg.scan(/([A-Z][a-z]?)(\d*)/).each do |k,v|
13
+ self[k.downcase.to_sym] = (v == '' ? 1 : v.to_i)
14
+ end
15
+ else
16
+ self.merge!(arg)
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -39,12 +39,20 @@ module MS
39
39
  def mzs
40
40
  @data_arrays[0]
41
41
  end
42
+
43
+ def mzs=(ar)
44
+ @data_arrays[0] = ar
45
+ end
42
46
 
43
47
  # An array of the intensities data, corresponding to mzs.
44
48
  def intensities
45
49
  @data_arrays[1]
46
50
  end
47
51
 
52
+ def intensities=(ar)
53
+ @data_arrays[1] = ar
54
+ end
55
+
48
56
  def mzs_and_intensities
49
57
  [@data_arrays[0], @data_arrays[1]]
50
58
  end
data/mspire.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "mspire"
8
- s.version = "0.6.24"
8
+ s.version = "0.6.25"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["John T. Prince", "Simon Chiang"]
@@ -58,10 +58,12 @@ Gem::Specification.new do |s|
58
58
  "lib/ms/ident/search.rb",
59
59
  "lib/ms/isotope.rb",
60
60
  "lib/ms/isotope/aa.rb",
61
+ "lib/ms/isotope/distribution.rb",
61
62
  "lib/ms/isotope/nist_isotope_info.yml",
62
63
  "lib/ms/mascot.rb",
63
64
  "lib/ms/mass.rb",
64
65
  "lib/ms/mass/aa.rb",
66
+ "lib/ms/molecular_formula.rb",
65
67
  "lib/ms/mzml.rb",
66
68
  "lib/ms/mzml/activation.rb",
67
69
  "lib/ms/mzml/chromatogram.rb",
@@ -126,8 +128,10 @@ Gem::Specification.new do |s|
126
128
  "spec/ms/ident/pepxml_spec.rb",
127
129
  "spec/ms/ident/protein_group_spec.rb",
128
130
  "spec/ms/isotope/aa_spec.rb",
131
+ "spec/ms/isotope/distribution_spec.rb",
129
132
  "spec/ms/isotope_spec.rb",
130
133
  "spec/ms/mass_spec.rb",
134
+ "spec/ms/molecular_formula_spec.rb",
131
135
  "spec/ms/mzml/cv_spec.rb",
132
136
  "spec/ms/mzml/data_array_spec.rb",
133
137
  "spec/ms/mzml/file_content_spec.rb",
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ require 'ms/isotope/distribution'
4
+
5
+ describe 'MS::Isotope::Distribution class methods' do
6
+ before do
7
+ @data = [1.0, 0.08919230588715289, 0.017894161377222082, 0.0013573997600723623, 0.0001398330738144092]
8
+ end
9
+
10
+ it 'can calculate isotope distributions' do
11
+ MS::Isotope::Distribution.calculate('C8O7', :max).should == @data
12
+ end
13
+
14
+ # no m/z values, just mass values
15
+ it 'can calculate isotope distribution spectrum' do
16
+ spec = MS::Isotope::Distribution.spectrum('C8O7', :max)
17
+ spec.mzs.should == [207.96440233692, 208.97306725252, 209.98173216812, 210.99039708372, 211.99906199932002]
18
+ spec.intensities.should == [1.0, 0.08919230588715289, 0.017894161377222082, 0.0013573997600723623, 0.0001398330738144092]
19
+ end
20
+ end
data/spec/ms/mass_spec.rb CHANGED
@@ -1,8 +1,42 @@
1
1
  require 'spec_helper'
2
2
 
3
+ require 'ms/mass'
4
+
3
5
  describe 'MS::Mass' do
4
6
  it 'can access elemental masses by string or symbol' do
5
- MS::Mass::MONO['h'].should be_a_kind_of Float
6
- MS::Mass::MONO[:h].should be_a_kind_of Float
7
+ {
8
+ 'c' => 12.0, # +
9
+ 'br' => 78.9183361, # +
10
+ 'd' => 2.014101779, # +
11
+ 'f' => 18.99840322, # +
12
+ 'n' => 14.003074, # +
13
+ 'o' => 15.99491463, # +
14
+ 'na' => 22.9897677, # +
15
+ 'p' => 30.973762, # +
16
+ 's' => 31.9720707, # +
17
+ 'li' => 7.016003, # +
18
+ 'cl' => 34.96885272, # +
19
+ 'k' => 38.9637074, # +
20
+ 'si' => 27.9769265325,
21
+ 'i' => 126.904473, # +
22
+ 'h+' => 1.00727646677,
23
+ 'h' => 1.007825035, # +
24
+ 'h2o' => 18.0105647,
25
+ 'oh' => 17.002739665,
26
+ 'e' => 0.0005486,
27
+ 'se' => 79.9165196
28
+ }.each do |el, mass|
29
+ MS::Mass::MONO[el].should_not be_nil
30
+ MS::Mass::MONO[el].should == MS::Mass::MONO[el.to_sym]
31
+ MS::Mass::MONO[el].should be_within(0.00001).of(mass)
32
+ end
33
+
34
+
35
+ { h: 1.00794, he: 4.002602, ni: 58.6934 }.each do |el, mass|
36
+ MS::Mass::AVG[el].should_not be_nil
37
+ MS::Mass::AVG[el].should == MS::Mass::AVG[el.to_sym]
38
+ MS::Mass::AVG[el].should be_within(0.00001).of(mass)
39
+ end
40
+
7
41
  end
8
42
  end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ require 'ms/molecular_formula'
4
+
5
+ describe MS::MolecularFormula do
6
+
7
+ it 'can be initialized with a String or Hash' do
8
+ data = {h: 22, c: 12, n: 1, o: 3, s: 2}
9
+ mf = MS::MolecularFormula.new "H22BeC12N1O3S2Li2"
10
+ mf.should == {:h=>22, :be=>1, :c=>12, :n=>1, :o=>3, :s=>2, :li=>2}
11
+ mf = MS::MolecularFormula.new(data)
12
+ mf.should == data
13
+ end
14
+
15
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mspire
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.24
4
+ version: 0.6.25
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -14,7 +14,7 @@ date: 2012-03-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: nokogiri
17
- requirement: &13307340 !ruby/object:Gem::Requirement
17
+ requirement: &13676060 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '1.5'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *13307340
25
+ version_requirements: *13676060
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: bsearch
28
- requirement: &13323080 !ruby/object:Gem::Requirement
28
+ requirement: &13674700 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: 1.5.0
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *13323080
36
+ version_requirements: *13674700
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: andand
39
- requirement: &13322420 !ruby/object:Gem::Requirement
39
+ requirement: &13673200 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: 1.3.1
45
45
  type: :runtime
46
46
  prerelease: false
47
- version_requirements: *13322420
47
+ version_requirements: *13673200
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: obo
50
- requirement: &13321500 !ruby/object:Gem::Requirement
50
+ requirement: &13672440 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: 0.1.0
56
56
  type: :runtime
57
57
  prerelease: false
58
- version_requirements: *13321500
58
+ version_requirements: *13672440
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: builder
61
- requirement: &13320060 !ruby/object:Gem::Requirement
61
+ requirement: &13671860 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ! '>='
@@ -66,10 +66,10 @@ dependencies:
66
66
  version: 3.0.0
67
67
  type: :runtime
68
68
  prerelease: false
69
- version_requirements: *13320060
69
+ version_requirements: *13671860
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: trollop
72
- requirement: &13319460 !ruby/object:Gem::Requirement
72
+ requirement: &13687020 !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
75
  - - ! '>='
@@ -77,10 +77,10 @@ dependencies:
77
77
  version: 1.16.2
78
78
  type: :runtime
79
79
  prerelease: false
80
- version_requirements: *13319460
80
+ version_requirements: *13687020
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: rspec
83
- requirement: &13318520 !ruby/object:Gem::Requirement
83
+ requirement: &13685880 !ruby/object:Gem::Requirement
84
84
  none: false
85
85
  requirements:
86
86
  - - ~>
@@ -88,10 +88,10 @@ dependencies:
88
88
  version: '2.6'
89
89
  type: :development
90
90
  prerelease: false
91
- version_requirements: *13318520
91
+ version_requirements: *13685880
92
92
  - !ruby/object:Gem::Dependency
93
93
  name: jeweler
94
- requirement: &13317560 !ruby/object:Gem::Requirement
94
+ requirement: &13684660 !ruby/object:Gem::Requirement
95
95
  none: false
96
96
  requirements:
97
97
  - - ~>
@@ -99,10 +99,10 @@ dependencies:
99
99
  version: 1.5.2
100
100
  type: :development
101
101
  prerelease: false
102
- version_requirements: *13317560
102
+ version_requirements: *13684660
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: rcov
105
- requirement: &13316940 !ruby/object:Gem::Requirement
105
+ requirement: &13683500 !ruby/object:Gem::Requirement
106
106
  none: false
107
107
  requirements:
108
108
  - - ! '>='
@@ -110,7 +110,7 @@ dependencies:
110
110
  version: '0'
111
111
  type: :development
112
112
  prerelease: false
113
- version_requirements: *13316940
113
+ version_requirements: *13683500
114
114
  description: mass spectrometry proteomics, lipidomics, and tools, a rewrite of mspire,
115
115
  merging of ms-* gems
116
116
  email: jtprince@gmail.com
@@ -161,10 +161,12 @@ files:
161
161
  - lib/ms/ident/search.rb
162
162
  - lib/ms/isotope.rb
163
163
  - lib/ms/isotope/aa.rb
164
+ - lib/ms/isotope/distribution.rb
164
165
  - lib/ms/isotope/nist_isotope_info.yml
165
166
  - lib/ms/mascot.rb
166
167
  - lib/ms/mass.rb
167
168
  - lib/ms/mass/aa.rb
169
+ - lib/ms/molecular_formula.rb
168
170
  - lib/ms/mzml.rb
169
171
  - lib/ms/mzml/activation.rb
170
172
  - lib/ms/mzml/chromatogram.rb
@@ -229,8 +231,10 @@ files:
229
231
  - spec/ms/ident/pepxml_spec.rb
230
232
  - spec/ms/ident/protein_group_spec.rb
231
233
  - spec/ms/isotope/aa_spec.rb
234
+ - spec/ms/isotope/distribution_spec.rb
232
235
  - spec/ms/isotope_spec.rb
233
236
  - spec/ms/mass_spec.rb
237
+ - spec/ms/molecular_formula_spec.rb
234
238
  - spec/ms/mzml/cv_spec.rb
235
239
  - spec/ms/mzml/data_array_spec.rb
236
240
  - spec/ms/mzml/file_content_spec.rb