diadem 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|