diadem 0.0.2
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 +7 -0
- data/.gitignore +19 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +18 -0
- data/README.md +35 -0
- data/Rakefile +19 -0
- data/bin/diadem-cubic.rb +5 -0
- data/diadem.gemspec +39 -0
- data/lib/diadem/calculator.rb +159 -0
- data/lib/diadem/cubic/commandline.rb +55 -0
- data/lib/diadem/cubic.rb +84 -0
- data/lib/diadem/distribution.rb +21 -0
- data/lib/diadem/enrichment.rb +30 -0
- data/lib/diadem/isotope_distribution.rb +63 -0
- data/lib/diadem/isotope_incorporation_table.rb +6 -0
- data/lib/diadem/version.rb +3 -0
- data/spec/diadem/calculator_spec.rb +94 -0
- data/spec/diadem/cubic_spec.rb +26 -0
- data/spec/diadem/isotope_distribution_spec.rb +40 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/testfiles/input.csv +3 -0
- data/spec/testfiles/input.cubic.csv +4 -0
- metadata +187 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e43300c479c268f5db7b16b84b3b807e449757ad
|
4
|
+
data.tar.gz: 3a930a150873d4b004cb0d677992c98c0e4c2c4e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 17de7bc9c431c7917fb3136fc01ef8aace5a4ae383f615971ec3be8525d85dd722775ec05e6b259d2f869648a52b66c3eda14d9b2ee0cfe2d8db6d1a7c2609af
|
7
|
+
data.tar.gz: ffd5b0ace3d2cbb6f761d5e329afe3c961e96ca8e3311d4e68000b79af23e8423b9105bb2931f9d4ed1019b17a4e2c5eec120e1526426e194f0c10a2ef40cdc9
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2013 Brigham Young University
|
2
|
+
Authored by: John T. Prince with guidance from John C. Price
|
3
|
+
|
4
|
+
Please contact the authors if you would like to make arrangements to obtain
|
5
|
+
the software under a different license.
|
6
|
+
|
7
|
+
This program is free software: you can redistribute it and/or modify it under
|
8
|
+
the terms of the GNU General Public License as published by the Free Software
|
9
|
+
Foundation, either version 3 of the License, or (at your option) any later
|
10
|
+
version.
|
11
|
+
|
12
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
13
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
14
|
+
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
15
|
+
details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU General Public License along with
|
18
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Diadem
|
2
|
+
|
3
|
+
Tools for performing mass isotopomer distribution analysis (MIDA). Basically,
|
4
|
+
this is dynamic isotope analysis useful for mass spectrometry experiments
|
5
|
+
involving protein turnover.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
NOTE: requires ruby >= 2.0
|
10
|
+
|
11
|
+
Until the Mercury7 algorithm is implemented you will need the fftw3 gem
|
12
|
+
installed. It depends on the fftw3 library. On Ubuntu/Debian, it's as easy
|
13
|
+
as this:
|
14
|
+
|
15
|
+
sudo apt-get install libfftw3-dev
|
16
|
+
|
17
|
+
Then
|
18
|
+
|
19
|
+
sudo gem install diadem
|
20
|
+
|
21
|
+
## Examples
|
22
|
+
|
23
|
+
Run diadem-cubic.rb from the commandline with no args to get help:
|
24
|
+
|
25
|
+
diadem-cubic.rb
|
26
|
+
|
27
|
+
## LICENSE
|
28
|
+
|
29
|
+
GNU Public License version 3 (see LICENSE.txt). Please contact the authors for
|
30
|
+
consideration of releasing the software under different terms.
|
31
|
+
|
32
|
+
## Acronym
|
33
|
+
|
34
|
+
Diadem stands for Dynamic Isotope Analysis DEMystified or maybe Dynamic Isotope
|
35
|
+
Analysis DEMarcated.
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require 'rspec/core'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
6
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
7
|
+
end
|
8
|
+
|
9
|
+
task :default => :spec
|
10
|
+
|
11
|
+
require 'rdoc/task'
|
12
|
+
Rake::RDocTask.new do |rdoc|
|
13
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
14
|
+
|
15
|
+
rdoc.rdoc_dir = 'rdoc'
|
16
|
+
rdoc.title = "rubabel #{version}"
|
17
|
+
rdoc.rdoc_files.include('README*')
|
18
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
19
|
+
end
|
data/bin/diadem-cubic.rb
ADDED
data/diadem.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'diadem/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "diadem"
|
8
|
+
spec.version = Diadem::VERSION
|
9
|
+
spec.authors = ["John Prince"]
|
10
|
+
spec.email = ["jtprince@gmail.com"]
|
11
|
+
spec.description = %q{Dynamic isotope analysis for mass spectrometry isotope experiments. Calculates and visualizes varying isotope ratios and allows the user fine control over incorporation rates.}
|
12
|
+
spec.summary = %q{Dynamic isotope analysis for mass spectrometry isotope experiments}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
[
|
22
|
+
["mspire", "~> 0.10.0"],
|
23
|
+
["fftw3", "~> 0.3"],
|
24
|
+
].each do |args|
|
25
|
+
spec.add_dependency(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
[
|
29
|
+
["bundler", "~> 1.3"],
|
30
|
+
["rake"],
|
31
|
+
["rspec", "~> 2.13.0"],
|
32
|
+
["rdoc", "~> 3.12"],
|
33
|
+
["simplecov"],
|
34
|
+
["gnuplot", "~> 2.6.2"],
|
35
|
+
].each do |args|
|
36
|
+
spec.add_development_dependency(*args)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'matrix'
|
2
|
+
|
3
|
+
require "diadem/version"
|
4
|
+
require "diadem/enrichment"
|
5
|
+
require "diadem/distribution"
|
6
|
+
require 'mspire/molecular_formula'
|
7
|
+
require 'mspire/isotope/distribution'
|
8
|
+
|
9
|
+
module Diadem
|
10
|
+
class Calculator
|
11
|
+
# a match (a regex or a String of length 1) that indicates which amino
|
12
|
+
# acid should be modified, diff_formula is an Mspire::MolecularFormula
|
13
|
+
# object, gain is whether the molecular formula is added or subtracted
|
14
|
+
# (boolean, default true). static is boolean, default true. match_block
|
15
|
+
# by default will merely return the thing being matched (which is good
|
16
|
+
# behavior for static mods)
|
17
|
+
Modification = Struct.new(:match, :diff_formula, :gain, :static, :match_block) do
|
18
|
+
def initialize(*args, &_match_block)
|
19
|
+
(_char, _formula, _gain, _static) = args
|
20
|
+
_gain.nil? && ( _gain=true )
|
21
|
+
_static.nil? && ( _static=true )
|
22
|
+
_match_block.nil? && (_match_block=Diadem::Calculator::Modification::STATIC_MATCH_BLOCK)
|
23
|
+
super(_char, _formula, _gain, _static, _match_block)
|
24
|
+
end
|
25
|
+
|
26
|
+
# the arithmetic sign as a symbol: :+ or :-
|
27
|
+
def sign
|
28
|
+
gain ? :+ : :-
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Modification
|
33
|
+
VAR_MATCH_BLOCK = lambda(&:upcase)
|
34
|
+
STATIC_MATCH_BLOCK = lambda {|match| match }
|
35
|
+
|
36
|
+
MF = Mspire::MolecularFormula
|
37
|
+
OXIDIZED_METHIONINE = Modification.new('m', MF['O'], &VAR_MATCH_BLOCK)
|
38
|
+
# aka methylcarboxamido
|
39
|
+
CARBAMIDOMETHYL = Modification.new('C', MF['C2H3NO'])
|
40
|
+
|
41
|
+
DEFAULT_STATIC_MODS = [CARBAMIDOMETHYL]
|
42
|
+
DEFAULT_VAR_MODS = [OXIDIZED_METHIONINE]
|
43
|
+
DEFAULT_MODS = DEFAULT_STATIC_MODS + DEFAULT_VAR_MODS
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
Info = Struct.new(:orig_aaseq, :clean_aaseq, :formula, :penetration, :masses, :mods)
|
48
|
+
|
49
|
+
class Polynomial < Array ; end
|
50
|
+
|
51
|
+
class << self
|
52
|
+
# from http://rosettacode.org/wiki/Polynomial_regression#Ruby. Returns
|
53
|
+
# a Polynomial object
|
54
|
+
def polyfit(x, y, degree)
|
55
|
+
x_data = x.map {|xi| (0..degree).map { |pow| (xi**pow).to_f } }
|
56
|
+
|
57
|
+
mx = Matrix[*x_data]
|
58
|
+
my = Matrix.column_vector(y)
|
59
|
+
|
60
|
+
Diadem::Calculator::Polynomial.new( ((mx.t * mx).inv * mx.t * my).transpose.to_a[0] )
|
61
|
+
end
|
62
|
+
|
63
|
+
# returns new isotopes, properly enriched.
|
64
|
+
def enrich_isotope(isotopes, mass_number, fraction=1.0)
|
65
|
+
new_isotopes = isotopes.map(&:dup)
|
66
|
+
leftover_fraction = 1.0 - fraction
|
67
|
+
new_isotopes.each {|isot| isot.relative_abundance *= leftover_fraction }
|
68
|
+
isot_to_enrich = new_isotopes.find {|isot| isot.mass_number == mass_number }
|
69
|
+
isot_to_enrich.relative_abundance += fraction
|
70
|
+
new_isotopes
|
71
|
+
end
|
72
|
+
|
73
|
+
# related intensities
|
74
|
+
def distributions_to_polynomials(enrichments, distributions, num=5, degree=2)
|
75
|
+
distributions.map {|dist| dist.intensities[0,num] }.transpose.each_with_index.map do |ar, m|
|
76
|
+
polyfit(enrichments, ar, degree)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# returns spectra objects. The isotope_table handed in will not be altered
|
82
|
+
def initialize(element=:H, mass_number=2, penetration_table=Enrichment::AA_TABLE, isotope_table=Mspire::Isotope::BY_ELEMENT, round=false)
|
83
|
+
@round = round
|
84
|
+
@penetration_table, @element, @mass_number = penetration_table, element, mass_number
|
85
|
+
@isotope_table = dup_isotope_table(isotope_table)
|
86
|
+
end
|
87
|
+
|
88
|
+
def dup_isotope_table(table)
|
89
|
+
table.each.with_object({}) do |(key,val), new_table|
|
90
|
+
new_table[key] = val.map {|obj| obj.dup }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def max_penetration_fraction(aaseq, formula)
|
95
|
+
penetration = aaseq.each_char.inject(0.0) do |sum, aa|
|
96
|
+
sum + ( @penetration_table[aa] || 0.0 )
|
97
|
+
end
|
98
|
+
penetration = penetration.round if @round
|
99
|
+
@info.penetration = penetration
|
100
|
+
penetration.to_f / formula[@element]
|
101
|
+
end
|
102
|
+
|
103
|
+
# returns [formula_adjusted_for_mods, aaseq_with_no_mods]
|
104
|
+
def calculate_formula(aaseq_with_mods, mods)
|
105
|
+
mods.group_by(&:char).each do |modchar, mod|
|
106
|
+
aaseq_with_mods.each_char do |char|
|
107
|
+
if char == modchar
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
Mspire::MolecularFormula.from_aaseq(aaseq)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Returns [distributions, info]. Interprets lowercase m as singly oxidized methionine.
|
117
|
+
def calculate_isotope_distributions(aaseq, enrichments, normalize_type: :total, mods: Diadem::Calculator::Modification::DEFAULT_MODS)
|
118
|
+
@info = Info.new
|
119
|
+
pct_cutoff = nil
|
120
|
+
|
121
|
+
mf = Mspire::MolecularFormula
|
122
|
+
aaseq_up = aaseq
|
123
|
+
subtract_formula = mf.new
|
124
|
+
add_formula = mf.new
|
125
|
+
matched_mods = []
|
126
|
+
mods.each do |mod|
|
127
|
+
delta_formula = mod.gain ? add_formula : subtract_formula
|
128
|
+
aaseq_up = aaseq_up.gsub(mod.match) do |match|
|
129
|
+
matched_mods << [match, mod]
|
130
|
+
delta_formula.add!(mod.diff_formula)
|
131
|
+
mod.match_block.call(match)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
@info.mods = matched_mods
|
135
|
+
|
136
|
+
formula = mf.from_aaseq(aaseq_up)
|
137
|
+
formula += add_formula
|
138
|
+
formula -= subtract_formula
|
139
|
+
@info.formula = formula
|
140
|
+
|
141
|
+
max_pen_frac = max_penetration_fraction(aaseq_up, formula)
|
142
|
+
|
143
|
+
orig_isotopes = @isotope_table[@element]
|
144
|
+
|
145
|
+
distributions = enrichments.map do |enrich_frac|
|
146
|
+
effective_fraction = max_pen_frac * enrich_frac
|
147
|
+
@isotope_table[@element] = Diadem::Calculator.enrich_isotope(orig_isotopes, @mass_number, effective_fraction)
|
148
|
+
spectrum = formula.isotope_distribution_spectrum(normalize_type, pct_cutoff, @isotope_table)
|
149
|
+
@isotope_table[@element] = orig_isotopes
|
150
|
+
@info.masses = spectrum.mzs unless @info.masses
|
151
|
+
Diadem::Distribution.new( spectrum.intensities )
|
152
|
+
end
|
153
|
+
[distributions, @info]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module Diadem
|
5
|
+
module Cubic
|
6
|
+
module Commandline
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def parse(argv)
|
10
|
+
make_range = ->(start,stop,step) { Range.new(start, stop).step(step) }
|
11
|
+
|
12
|
+
start = 0.0
|
13
|
+
stop = 0.1
|
14
|
+
step = 0.002
|
15
|
+
opt = OpenStruct.new( {
|
16
|
+
carbamidomethyl: true,
|
17
|
+
oxidized_met: true,
|
18
|
+
element: :H,
|
19
|
+
mass_number: 2,
|
20
|
+
range: make_range[ start, stop, step ],
|
21
|
+
degree: 3,
|
22
|
+
header: true,
|
23
|
+
num_isotopomers: 5,
|
24
|
+
} )
|
25
|
+
|
26
|
+
parser = OptionParser.new do |op|
|
27
|
+
prog = File.basename($0)
|
28
|
+
op.banner = "usage: #{prog} <AASEQ> ..."
|
29
|
+
op.separator " or: #{prog} <aaseqs>.csv"
|
30
|
+
op.separator " <aaseqs>.csv is a single column of AA sequences (no header)"
|
31
|
+
op.separator ""
|
32
|
+
op.separator "output: tab delimited to stdout if AASEQ"
|
33
|
+
op.separator " <aaseqs>#{Diadem::Cubic::FILE_EXT} if csv input"
|
34
|
+
op.separator ""
|
35
|
+
op.separator "options:"
|
36
|
+
op.on("-e", "--element <#{opt.element}>", "element with isotopic label") {|v| opt.element = v.to_sym }
|
37
|
+
op.on("-m", "--mass-number <#{opt.mass_number}>", Integer, "the labeled element mass number") {|v| opt.mass_number = v }
|
38
|
+
op.on("--no-carbamidomethyl", "do not use this mod by default") { opt.carbamidomethyl = false }
|
39
|
+
op.on("--range <start:stop:step>", "the underlying input values (#{[start, stop, step].join(':')})") {|v| opt.range = make_range[ *v.split(':') ] }
|
40
|
+
op.on("--degree <#{opt.degree}>", Integer, "the degree polynomial") {|v| opt.degree = v }
|
41
|
+
op.on("--num-isotopomers <#{opt.num_isotopomers}>", Integer, "the number of isotopomers to calculate") {|v| opt.num_isotopomers = v }
|
42
|
+
op.on("--no-header", "don't print a header line") {|v| opt.header = false }
|
43
|
+
end
|
44
|
+
parser.parse!(argv)
|
45
|
+
if argv.size == 0
|
46
|
+
puts parser
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
[argv, opt]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/diadem/cubic.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'diadem/cubic/commandline'
|
2
|
+
require 'diadem/calculator'
|
3
|
+
require 'csv'
|
4
|
+
|
5
|
+
module Diadem
|
6
|
+
module Cubic
|
7
|
+
|
8
|
+
Isotope = Struct.new(:element, :mass_number)
|
9
|
+
Peptide = Struct.new(:aaseq, :isotope, :enrichments)
|
10
|
+
Enrichment = Struct.new(:fraction, :distribution)
|
11
|
+
|
12
|
+
FILE_EXT = '.cubic.csv'
|
13
|
+
class << self
|
14
|
+
# returns the filename of the output if given a filename, or nil
|
15
|
+
def run(argv)
|
16
|
+
(argv, opt) = Diadem::Cubic::Commandline.parse(argv)
|
17
|
+
opt.isotope = Diadem::Cubic::Isotope.new( opt.element, opt.mass_number )
|
18
|
+
opt.delim = ","
|
19
|
+
(out, aaseqs) =
|
20
|
+
if is_filename?(argv.first)
|
21
|
+
arg = argv.first
|
22
|
+
base = arg.chomp(File.extname(arg))
|
23
|
+
[File.open(base + FILE_EXT, 'w'), CSV.read(arg).map(&:first)]
|
24
|
+
else
|
25
|
+
[$stdout, argv]
|
26
|
+
end
|
27
|
+
calc = Diadem::Calculator.new( *opt.isotope.values )
|
28
|
+
|
29
|
+
if opt.header
|
30
|
+
cats = %w(sequence mods formula mass n)
|
31
|
+
isotopomers = *opt.num_isotopomers.times.map {|n| "M#{n}" }
|
32
|
+
cats.push(*isotopomers)
|
33
|
+
isotopomers.each do |label|
|
34
|
+
(opt.degree).downto(0) do |coeff|
|
35
|
+
cats << [label, "coeff", coeff].join("_")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
out.puts cats.join(opt.delim)
|
39
|
+
end
|
40
|
+
|
41
|
+
aaseqs.each do |aaseq|
|
42
|
+
# we cannot ensure the base 0% has been included in the range, so
|
43
|
+
# calculate it separately
|
44
|
+
mods = []
|
45
|
+
if opt.carbamidomethyl
|
46
|
+
mods << Diadem::Calculator::Modification::CARBAMIDOMETHYL
|
47
|
+
end
|
48
|
+
if opt.oxidized_met
|
49
|
+
mods << Diadem::Calculator::Modification::OXIDIZED_METHIONINE
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
(distributions, info) = calc.calculate_isotope_distributions(aaseq, opt.range.dup, mods: mods)
|
54
|
+
polynomials = Diadem::Calculator.distributions_to_polynomials(opt.range.to_a, distributions, opt.num_isotopomers, opt.degree)
|
55
|
+
|
56
|
+
zero_pct_dist =
|
57
|
+
if opt.range.first == 0.0
|
58
|
+
distributions.first
|
59
|
+
else
|
60
|
+
(dists, info) = calc.calculate_isotope_distributions(aaseq, [0.0])
|
61
|
+
zero_pct_dist = dists.first
|
62
|
+
end
|
63
|
+
|
64
|
+
modinfo = info.mods.map {|match, mod| "#{match}:#{mod.sign}#{mod.diff_formula}" }.join(' ')
|
65
|
+
line = [aaseq, modinfo, info.formula, info.formula.mass.round(6), info.penetration]
|
66
|
+
line.push *zero_pct_dist.intensities[0,opt.num_isotopomers].map {|v| v.round(6) }
|
67
|
+
polynomials.each do |coeffs|
|
68
|
+
line.push *coeffs.reverse
|
69
|
+
end
|
70
|
+
out.puts line.join(opt.delim)
|
71
|
+
end
|
72
|
+
if out.respond_to?(:path)
|
73
|
+
out.close
|
74
|
+
out.path
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def is_filename?(arg)
|
79
|
+
arg.include?('.')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
module Diadem
|
3
|
+
class Distribution
|
4
|
+
attr_accessor :intensities
|
5
|
+
|
6
|
+
def initialize(intensities)
|
7
|
+
@intensities = intensities
|
8
|
+
end
|
9
|
+
|
10
|
+
# returns self
|
11
|
+
def resize!(num)
|
12
|
+
newar = @intensities.dup
|
13
|
+
to_pad = num - @intensities.size
|
14
|
+
unless to_pad <= 0
|
15
|
+
to_pad.times { newar << 0.0 }
|
16
|
+
end
|
17
|
+
@intensities.replace( newar[0,num] )
|
18
|
+
self
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module Diadem
|
3
|
+
module Enrichment
|
4
|
+
AA_TABLE = {
|
5
|
+
'A' => 4,
|
6
|
+
'R' => 3.43,
|
7
|
+
'N' => 1.89,
|
8
|
+
'D' => 1.89,
|
9
|
+
'C' => 1.62,
|
10
|
+
'E' => 3.95,
|
11
|
+
'Q' => 3.95,
|
12
|
+
'G' => 2.06,
|
13
|
+
'H' => 2.88,
|
14
|
+
'I' => 1,
|
15
|
+
'L' => 0.6,
|
16
|
+
'K' => 0.54,
|
17
|
+
'M' => 1.12,
|
18
|
+
'F' => 0.32,
|
19
|
+
'P' => 2.59,
|
20
|
+
'S' => 2.61,
|
21
|
+
'T' => 0.2,
|
22
|
+
'Y' => 0.42,
|
23
|
+
'W' => 0.0,
|
24
|
+
'V' => 0.56,
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'mspire/molecular_formula'
|
2
|
+
require 'mspire/isotope'
|
3
|
+
require 'fftw3'
|
4
|
+
|
5
|
+
module Diadem
|
6
|
+
|
7
|
+
class IsotopeDistribution
|
8
|
+
DEFAULT_ISOTOPE_TABLE = Mspire::Isotope::BY_ELEMENT
|
9
|
+
|
10
|
+
# should always add up to 1
|
11
|
+
attr_accessor :intensities
|
12
|
+
# should be inclusive of last value
|
13
|
+
attr_accessor :nucleon_start
|
14
|
+
def initialize(intensities=[], nucleon_start=0)
|
15
|
+
@intensities, @nucleon_start = intensities, nucleon_start
|
16
|
+
end
|
17
|
+
|
18
|
+
def nucleon_end
|
19
|
+
nucleon_start + intensities.size - 1
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
|
24
|
+
def from_formula(formula)
|
25
|
+
Mspire::MolecularFormula[formula].isotope_distribution
|
26
|
+
end
|
27
|
+
|
28
|
+
# returns a new distribution, uses equal weights if none given
|
29
|
+
def average(distributions, weights=nil)
|
30
|
+
weights ||= Array.new(distributions.size, 1)
|
31
|
+
min_nucleon_num = distributions.map(&:nucleon_start).min
|
32
|
+
max_nucleon_num = distributions.map(&:nucleon_end).max
|
33
|
+
|
34
|
+
new_intensity_arrays = distributions.zip(weights).map do |dist, weight|
|
35
|
+
new_pcts = dist.intensities.dup
|
36
|
+
right_pad = max_nucleon_num - dist.nucleon_end
|
37
|
+
left_pad = dist.nucleon_start - min_nucleon_num
|
38
|
+
[[right_pad, new_pcts.size], [left_pad, 0]].each do |pad, loc|
|
39
|
+
new_pcts[loc,0] = Array.new(pad, 0.0)
|
40
|
+
end
|
41
|
+
new_pcts.map! {|v| v * weight }
|
42
|
+
new_pcts
|
43
|
+
end
|
44
|
+
|
45
|
+
summed_intensities = new_intensity_arrays.transpose.map do |col|
|
46
|
+
col.reduce(:+)
|
47
|
+
end
|
48
|
+
|
49
|
+
new_dist = self.new(summed_intensities, min_nucleon_num)
|
50
|
+
new_dist.normalize!
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# normalizes intensity values and returns self
|
55
|
+
def normalize!(normalize_to=1.0)
|
56
|
+
sum = intensities.reduce(:+)
|
57
|
+
intensities.map! {|v| (v.to_f/sum)*normalize_to }
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'csv'
|
3
|
+
|
4
|
+
require 'diadem/calculator'
|
5
|
+
|
6
|
+
Isotope = Struct.new(:element, :mass_number)
|
7
|
+
Peptide = Struct.new(:aaseq, :isotope, :enrichments)
|
8
|
+
Enrichment = Struct.new(:fraction, :distribution)
|
9
|
+
|
10
|
+
# returns [fractions, [array_of_intensity1s, array_of_intensity2s ...]
|
11
|
+
def transpose_enrichments(peptide)
|
12
|
+
fractions = peptide.enrichments.map(&:fraction)
|
13
|
+
[fractions, peptide.enrichments.map(&:distribution).transpose]
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
describe 'calculating enrichments' do
|
18
|
+
|
19
|
+
it 'makes distributions' do
|
20
|
+
|
21
|
+
rows = CSV.read("gold_standards/output_tabular.csv")
|
22
|
+
mida_peptides = []
|
23
|
+
read_enrichments = false
|
24
|
+
rows.each_with_index do |row,i|
|
25
|
+
if row.compact.size == 0
|
26
|
+
read_enrichments = false
|
27
|
+
elsif read_enrichments
|
28
|
+
row.map!(&:to_f)
|
29
|
+
mida_peptides.last.enrichments << Enrichment.new( row[0], row[1..-1] )
|
30
|
+
elsif row[0] =~ /\AIsotope=/
|
31
|
+
(mass_number_s, element_s) = row[0].split('=').last.each_char.to_a
|
32
|
+
isotope = Isotope.new(element_s.to_sym, mass_number_s.to_i)
|
33
|
+
aaseq = rows[i-1].first.split(/\s+/).first
|
34
|
+
mida_peptides << Peptide.new(aaseq, isotope, [])
|
35
|
+
read_enrichments = true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
#mida_peptides.reject! {|me| me.aaseq.include?('m') }
|
39
|
+
|
40
|
+
[true, false].each do |round|
|
41
|
+
my_peptides = mida_peptides.map do |mida_peptide|
|
42
|
+
|
43
|
+
(element, mass_number) = mida_peptide.isotope.values
|
44
|
+
|
45
|
+
calc = Diadem::Calculator.new(element, mass_number, Diadem::Enrichment::AA_TABLE, Mspire::Isotope::BY_ELEMENT, round)
|
46
|
+
fractions = mida_peptide.enrichments.map(&:fraction)
|
47
|
+
(distributions, info) = calc.calculate_isotope_distributions(mida_peptide.aaseq, fractions)
|
48
|
+
|
49
|
+
my_peptide = Peptide.new( mida_peptide.aaseq, mida_peptide.isotope )
|
50
|
+
my_peptide.enrichments = distributions.zip(fractions).map do |distribution, fractions|
|
51
|
+
Enrichment.new( fractions, distribution.resize!(7) )
|
52
|
+
end
|
53
|
+
my_peptide
|
54
|
+
end
|
55
|
+
|
56
|
+
$PLOT = false
|
57
|
+
if $PLOT
|
58
|
+
require 'gnuplot'
|
59
|
+
mida_peptides.zip(my_peptides) do |mida, mine|
|
60
|
+
plottype = 'png'
|
61
|
+
base = mida.aaseq + "-ROUND:#{round}"
|
62
|
+
plotfile = base + ".#{plottype}"
|
63
|
+
mi = mida.isotope
|
64
|
+
|
65
|
+
Gnuplot.open do |gp|
|
66
|
+
Gnuplot::Plot.new(gp) do |plot|
|
67
|
+
|
68
|
+
plot.title [mida.aaseq, "el:#{mi.element}", "massnum:#{mi.mass_number}", "round:#{round}"].join(" ")
|
69
|
+
plot.terminal plottype
|
70
|
+
plot.output plotfile
|
71
|
+
plot.xlabel "label fraction"
|
72
|
+
plot.ylabel "relative intensity"
|
73
|
+
plot.yrange "[0:0.5]"
|
74
|
+
|
75
|
+
plot.data = []
|
76
|
+
|
77
|
+
mida_fracs_and_int_ars = transpose_enrichments(mida)
|
78
|
+
|
79
|
+
byu_fracs_and_ints_ars = transpose_enrichments(mine)
|
80
|
+
[:mida, mida_fracs_and_int_ars, :byu, byu_fracs_and_ints_ars].each_slice(2) do |name, (fracs, int_ars)|
|
81
|
+
int_ars.each_with_index do |ints, mnum|
|
82
|
+
plot.data << Gnuplot::DataSet.new( [fracs, ints] ) {|ds| ds.title = "#{name}-M#{mnum}"; ds.with = "lines" }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'csv'
|
3
|
+
|
4
|
+
require 'diadem/cubic'
|
5
|
+
|
6
|
+
describe Diadem::Cubic do
|
7
|
+
specify 'using an input file' do
|
8
|
+
filename = Diadem::Cubic.run( [TESTFILES + "/input.csv"], )
|
9
|
+
File.basename(filename).should == 'input.cubic.csv'
|
10
|
+
rows = CSV.read(filename)
|
11
|
+
rows.first.should == %w(sequence mods formula mass n M0 M1 M2 M3 M4 M0_coeff_3 M0_coeff_2 M0_coeff_1 M0_coeff_0 M1_coeff_3 M1_coeff_2 M1_coeff_1 M1_coeff_0 M2_coeff_3 M2_coeff_2 M2_coeff_1 M2_coeff_0 M3_coeff_3 M3_coeff_2 M3_coeff_1 M3_coeff_0 M4_coeff_3 M4_coeff_2 M4_coeff_1 M4_coeff_0)
|
12
|
+
rows.size.should == 4
|
13
|
+
lrow = rows.last
|
14
|
+
# these are verified
|
15
|
+
lrow[0,10].should == ["NEVHCmLGQSTCEMIR", "C:+C2H3NO C:+C2H3NO m:+O", "C77H129N25O28S4", "1979.832173", "32.56", "0.298777", "0.293168", "0.213061", "0.114555", "0.051392"]
|
16
|
+
# the below values are not verified for complete accuracy, but are frozen.
|
17
|
+
# I *have* verified that my polyfit gives exactly the same as numpy.polyfit
|
18
|
+
# I *have* verified that my fits give nearly the identical result when the
|
19
|
+
# formula is used to calculate the function and compared with the raw
|
20
|
+
# data.
|
21
|
+
coeff_exp = ["-392.23934817385657", "96.69007230820951", "-8.611345775533028", "0.2941872043446288", "274.6030329923823", "-32.519634396959496", "-1.9819130901305437", "0.3015660872075071", "349.4058191339298", "-74.1471126522828", "2.8594996757768354", "0.2129971981087685", "101.51558561078951", "-45.23875117790308", "3.95095594421288", "0.1114045333664326", "-125.24493326823091", "0.15596911712410133", "2.5230711874760186", "0.04912040472741169"]
|
22
|
+
lrow[10..-1].zip( coeff_exp ) do |mine, csv|
|
23
|
+
mine.to_f.should be_within(1e-5).of(csv.to_f)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'diadem/isotope_distribution'
|
4
|
+
|
5
|
+
|
6
|
+
#describe Diadem::IsotopeDistribution do
|
7
|
+
#before do
|
8
|
+
#@dists =
|
9
|
+
#[[1,2,1], 1,
|
10
|
+
#[2, 1, 1], 2,
|
11
|
+
#[4], 6
|
12
|
+
#].each_slice(2).map do |ints, start|
|
13
|
+
#Diadem::IsotopeDistribution.new( ints, start ).normalize!
|
14
|
+
#end
|
15
|
+
#end
|
16
|
+
|
17
|
+
#specify 'average with equal weights' do
|
18
|
+
#output = Diadem::IsotopeDistribution.average(@dists)
|
19
|
+
#[0.083, 0.333, 0.167, 0.083, 0.0, 0.333].zip(output.intensities) do |act, exp|
|
20
|
+
#act.should be_within(0.002).of(exp)
|
21
|
+
#end
|
22
|
+
#output.nucleon_start.should == 1
|
23
|
+
#output.nucleon_end.should == 6
|
24
|
+
#end
|
25
|
+
|
26
|
+
#specify 'average with unequal weights' do
|
27
|
+
#output = Diadem::IsotopeDistribution.average(@dists, [1,1,10])
|
28
|
+
#[0.021, 0.083, 0.042, 0.021, 0.0, 0.833].zip(output.intensities) do |act, exp|
|
29
|
+
#act.should be_within(0.002).of(exp)
|
30
|
+
#end
|
31
|
+
#output.nucleon_start.should == 1
|
32
|
+
#output.nucleon_end.should == 6
|
33
|
+
#end
|
34
|
+
|
35
|
+
#specify 'normalize!' do
|
36
|
+
#output = Diadem::IsotopeDistribution.new([2,2,2,2], 3).normalize!
|
37
|
+
#output.nucleon_start.should == 3
|
38
|
+
#output.intensities.should == [0.25, 0.25, 0.25, 0.25]
|
39
|
+
#end
|
40
|
+
#end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
|
4
|
+
require 'rspec'
|
5
|
+
|
6
|
+
require 'rspec/core/formatters/progress_formatter'
|
7
|
+
# doesn't say so much about pending guys
|
8
|
+
class QuietPendingFormatter < RSpec::Core::Formatters::ProgressFormatter
|
9
|
+
def example_pending(example)
|
10
|
+
output.print pending_color('*')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'rspec/core/formatters/documentation_formatter'
|
15
|
+
class QuietPendingDocFormatter < RSpec::Core::Formatters::DocumentationFormatter
|
16
|
+
def example_pending(example)
|
17
|
+
output.puts pending_color( "<pending>: #{example.execution_result[:pending_message]}" )
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
RSpec.configure do |config|
|
22
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
23
|
+
config.formatter = QuietPendingDocFormatter
|
24
|
+
config.color = true
|
25
|
+
end
|
26
|
+
|
27
|
+
TESTFILES = File.dirname(__FILE__) + "/testfiles"
|
@@ -0,0 +1,4 @@
|
|
1
|
+
sequence,mods,formula,mass,n,M0,M1,M2,M3,M4,M0_coeff_3,M0_coeff_2,M0_coeff_1,M0_coeff_0,M1_coeff_3,M1_coeff_2,M1_coeff_1,M1_coeff_0,M2_coeff_3,M2_coeff_2,M2_coeff_1,M2_coeff_0,M3_coeff_3,M3_coeff_2,M3_coeff_1,M3_coeff_0,M4_coeff_3,M4_coeff_2,M4_coeff_1,M4_coeff_0
|
2
|
+
LGADmEDLR,m:+O,C41H70N12O17S,1034.47026,19.540000000000003,0.556753,0.283781,0.115285,0.033992,0.008188,-271.9669543025388,83.87707865863915,-10.465171001547173,0.5549760242624675,447.26750757706844,-95.6467773946335,4.1767024133301724,0.2886473523635921,6.84299765300193,-28.68989673734115,4.13419674326592,0.11197392177809003,-142.35794452920663,15.157584520461455,1.7045563652845814,0.03326539309479602,-77.519961106925,17.24516248866918,0.37336969361968486,0.008718956309883851
|
3
|
+
NEVHTMLGQSTEEIR,,C71H118N22O27S,1742.825748,32.35,0.377313,0.332051,0.182291,0.074572,0.024703,-489.95684055041977,121.08399596787066,-10.824527731710008,0.3716306301733113,396.4694223063598,-53.6786513841365,-1.3631060138342357,0.34307099404888625,463.833104592279,-104.37963257827352,5.26331279186841,0.18182473265187887,26.202644313310657,-39.45052607309262,4.745738877395441,0.0692194335651921,-228.23593191536418,19.192095667466113,2.023880307456716,0.022424872233935855
|
4
|
+
NEVHCmLGQSTCEMIR,C:+C2H3NO C:+C2H3NO m:+O,C77H129N25O28S4,1979.832173,32.56,0.298777,0.293168,0.213061,0.114555,0.051392,-392.23934817385657,96.69007230820951,-8.611345775533028,0.2941872043446288,274.6030329923823,-32.519634396959496,-1.9819130901305437,0.3015660872075071,349.4058191339298,-74.1471126522828,2.8594996757768354,0.2129971981087685,101.51558561078951,-45.23875117790308,3.95095594421288,0.1114045333664326,-125.24493326823091,0.15596911712410133,2.5230711874760186,0.04912040472741169
|
metadata
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: diadem
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John Prince
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-09-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: mspire
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.10.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.10.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: fftw3
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.13.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.13.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rdoc
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.12'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.12'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simplecov
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: gnuplot
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 2.6.2
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ~>
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 2.6.2
|
125
|
+
description: Dynamic isotope analysis for mass spectrometry isotope experiments. Calculates
|
126
|
+
and visualizes varying isotope ratios and allows the user fine control over incorporation
|
127
|
+
rates.
|
128
|
+
email:
|
129
|
+
- jtprince@gmail.com
|
130
|
+
executables:
|
131
|
+
- diadem-cubic.rb
|
132
|
+
extensions: []
|
133
|
+
extra_rdoc_files: []
|
134
|
+
files:
|
135
|
+
- .gitignore
|
136
|
+
- Gemfile
|
137
|
+
- LICENSE.txt
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- bin/diadem-cubic.rb
|
141
|
+
- diadem.gemspec
|
142
|
+
- lib/diadem/calculator.rb
|
143
|
+
- lib/diadem/cubic.rb
|
144
|
+
- lib/diadem/cubic/commandline.rb
|
145
|
+
- lib/diadem/distribution.rb
|
146
|
+
- lib/diadem/enrichment.rb
|
147
|
+
- lib/diadem/isotope_distribution.rb
|
148
|
+
- lib/diadem/isotope_incorporation_table.rb
|
149
|
+
- lib/diadem/version.rb
|
150
|
+
- spec/diadem/calculator_spec.rb
|
151
|
+
- spec/diadem/cubic_spec.rb
|
152
|
+
- spec/diadem/isotope_distribution_spec.rb
|
153
|
+
- spec/spec_helper.rb
|
154
|
+
- spec/testfiles/input.csv
|
155
|
+
- spec/testfiles/input.cubic.csv
|
156
|
+
homepage: ''
|
157
|
+
licenses:
|
158
|
+
- MIT
|
159
|
+
metadata: {}
|
160
|
+
post_install_message:
|
161
|
+
rdoc_options: []
|
162
|
+
require_paths:
|
163
|
+
- lib
|
164
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
requirements: []
|
175
|
+
rubyforge_project:
|
176
|
+
rubygems_version: 2.0.3
|
177
|
+
signing_key:
|
178
|
+
specification_version: 4
|
179
|
+
summary: Dynamic isotope analysis for mass spectrometry isotope experiments
|
180
|
+
test_files:
|
181
|
+
- spec/diadem/calculator_spec.rb
|
182
|
+
- spec/diadem/cubic_spec.rb
|
183
|
+
- spec/diadem/isotope_distribution_spec.rb
|
184
|
+
- spec/spec_helper.rb
|
185
|
+
- spec/testfiles/input.csv
|
186
|
+
- spec/testfiles/input.cubic.csv
|
187
|
+
has_rdoc:
|