lib/molecules/calc.rb in bahuvrihi-molecules-0.1.1 vs lib/molecules/calc.rb in bahuvrihi-molecules-0.1.2

- old
+ new

@@ -8,105 +8,44 @@ end Unit.setup module Molecules - # :startdoc::manifest a mass calculator - # Calculates the mass of a molecule or empirical formula. The - # options can be used to alter the output (precision, mass - # calculation method etc.) You may enter compound formulae, or - # a list of formulae. In addition, polypeptides can be specified - # using the one-letter residue codes: + # :startdoc::manifest a mass calculator # - # % tap -- molecules/calc H2O - # I[17:09:00] 18.0105646863 Da H2O - # - # % tap -- molecules/calc H2O -u kg - # I[13:35:59] 2.99072e-026 kg H2O + # Calculates the mass of a molecule. Compound formulae are allowed and you may + # specify a list of formulae. The options can be used to alter the output (precision, + # mass calculation method etc.) # - # % tap -- molecules/calc 'C3H5NO + H2O' C50H73N15O11 -p 2 - # I[17:08:21] 89.05 Da C3H5NO + H2O - # I[17:08:21] 1059.56 Da C50H73N15O11 + # % tap run -- molecules/calc H2O + # I[17:08:00] 18.0105646863 Da H2O # - # % tap -- molecules/calc :RPPGFSPFR - # I[13:35:02] 1059.56 Da :RPPGFSPFR - # - # Furthermore, if a unimod path is specified in the configurations, - # unimod modifcations may be specified by name as the polypeptide - # termini. Use '%' signs as in a SQL query to shorten the name: - # - # % tap -- molecules/calc 'Acetyl:RPPGFSPFR:Hydroxyl%' --unimod-path <...> - # I[13:33:25] 1059.56 Da Acetyl:RPPGFSPFR:Hydroxyl% - # - # The unimod path must point to an sqlite3 ActiveUnimod database, and - # sqlite3-ruby must be installed for this feature to work. - # - # * ActiveUnimod[http://bioactive.rubyforge.org/] - # * sqlite3-ruby[http://rubyforge.org/projects/sqlite-ruby/] - # + # % tap run -- molecules/calc H2O --units yg --precision 6 + # I[17:08:21] 29.907243 yg H2O + # + # % tap run -- molecules/calc 'C3H5NO + H2O' C50H73N15O11 -p 2 + # I[17:08:53] 89.05 Da C3H5NO + H2O + # I[17:08:53] 1059.56 Da C50H73N15O11 + # class Calc < Tap::Task config :type, :monoisotopic # the mass type calculated config :precision, nil, :short => 'p' # the precision of the mass config :units, "Da", :short => 'u', &c.string # the mass unit reported config :composition, false, :short => 'c', &c.flag # reports the composition, not the formula - config :unimod_path, nil do |path| # the path to the unimod database - case - when path == nil then nil - when File.exists?(path) then path - else raise "path to unimod db does not exist: #{path}" - end - end - # Formulates a query for a modification matching code_name - # for the unimod database. If the code_name contains a '%' - # then the query will use a LIKE syntax, otherwise the - # code_name will be searced for exactly. - def mod_query(code_name) - # should do a rails-like escape on code_name - "SELECT code_name, composition FROM modifications WHERE code_name #{code_name.include?('%') ? 'LIKE' : '='} '#{code_name}'" + # Parses the formula string into an EmpiricalFormula. + # Can be used as a hook for more complicated formulae + # in subclases. + def parse(formula) + EmpiricalFormula.parse(formula) end - # Attempts to find and instantiate an EmpiricalFormula for - # a unimod modification matching code_name. - def find_mod(code_name) - raise "no unimod_path was specified" if unimod_path == nil - require 'sqlite3' unless Object.const_defined?(:SQLite3) - - results = [] - db = SQLite3::Database.new(unimod_path) - db.execute(mod_query(code_name)) do |row| - results << row - end - db.close - - case results.length - when 1 then EmpiricalFormula.parse_simple(results[0][1]) - when 0 then raise "could not find modification: #{code_name}" - else raise "multiple modifications found for: #{code_name} (#{results.collect {|result| result[0]}.join(', ')})" - end - end - - WATER = EmpiricalFormula.parse "H2O" - HYDROGEN = EmpiricalFormula.parse "H" - HYDROXIDE = EmpiricalFormula.parse "OH" - # Returns an array of the calculated masses, in the correct unit. def process(*formulae) - formulae.collect do |formula_str| - formula = EmpiricalFormula.parse(formula_str) do |str| - case str - when /^(.*?):([A-Z]+):?(.*)$/ - peptide = Libraries::Polypeptide.new($2) + WATER - peptide += find_mod($1) unless $1.to_s.empty? - peptide += find_mod($3) unless $3.to_s.empty? - peptide - else nil - end - end - - mass = formula.mass do |element| + formulae.collect do |formula_str| + mass = parse(formula_str).mass do |element| case type when :monoisotopic then element.mass when :average then element.std_atomic_weight.value else raise "unknown mass type: #{type}" end @@ -114,11 +53,11 @@ mass = Unit.new(mass, "Da").convert_to(units) unless precision == nil mass = Unit.new( Utils.round(mass.scalar, precision), units) end - - log mass, composition ? formula : formula_str + + log "#{mass.scalar} #{mass.units}", composition ? formula : formula_str mass end end \ No newline at end of file