class Mspire::MolecularFormula
Attributes
integer desribing the charge state mass calculations will add/remove electron mass from this
Public Class Methods
# File lib/mspire/molecular_formula.rb, line 8 def from_aaseq(aaseq, formula_hash=Mspire::Isotope::AA::FORMULAS) hash = aaseq.each_char.inject({}) do |hash,aa| hash.merge(formula_hash[aa]) {|hash,old,new| (old ? old : 0) + new } end hash[:H] += 2 hash[:O] += 1 self.new(hash) end
arg may be a String, Hash
, or MolecularFormula
object.
# File lib/mspire/molecular_formula.rb, line 28 def from_any(arg, charge=0) if arg.is_a?(String) from_string(arg, charge) else self.new(arg, arg.respond_to?(:charge) ? arg.charge : 0) end end
takes a string, with properly capitalized elements making up the formula. The elements may be in any order.
# File lib/mspire/molecular_formula.rb, line 19 def from_string(mol_form_str, charge=0) mf = self.new({}, charge) mol_form_str.scan(/([A-Z][a-z]?)(\d*)/).each do |k,v| mf[k.to_sym] = (v == '' ? 1 : v.to_i) end mf end
Takes a hash and an optional Integer expressing the charge
{H: 22, C: 12, N: 1, O: 3, S: 2} # case and string/sym doesn't matter
# File lib/mspire/molecular_formula.rb, line 45 def initialize(hash={}, charge=0) @charge = charge self.merge!(hash) end
Public Instance Methods
# File lib/mspire/molecular_formula.rb, line 86 def *(int) self.dup.mul!(int) end
returns a new formula object where all the atoms have been added up
# File lib/mspire/molecular_formula.rb, line 51 def +(*others) self.dup.add!(*others) end
returns a new formula object where all the formulas have been subtracted from the caller
# File lib/mspire/molecular_formula.rb, line 66 def -(*others) self.dup.sub!(*others) end
# File lib/mspire/molecular_formula.rb, line 99 def /(int) self.dup.div!(int) end
# File lib/mspire/molecular_formula.rb, line 159 def ==(other) old_equal(other) && self.charge == other.charge end
returns self
# File lib/mspire/molecular_formula.rb, line 56 def add!(*others) others.each do |other| self.merge!(other) {|key, oldval, newval| self[key] = oldval + newval } self.charge += other.charge end self end
# File lib/mspire/molecular_formula.rb, line 128 def avg_mass inject(0.0) {|sum,(el,cnt)| sum + (Mspire::Mass::Element::AVG[el]*cnt) } end
# File lib/mspire/molecular_formula.rb, line 103 def div!(int, also_do_charge=true) raise ArgumentError, "must be an integer" unless int.is_a?(Integer) self.each do |k,v| quotient, modulus = v.divmod(int) raise ArgumentError "all numbers must be divisible by int" unless modulus == 0 self[k] = quotient end if also_do_charge quotient, modulus = self.charge.divmod(int) raise ArgumentError "charge must be divisible by int" unless modulus == 0 self.charge = quotient end self end
Returns isotopic distribution beginning with the lightest possible peak. (for most molecules this will also be the monoisotopic peak)
Two cutoff protocols may be specified, percent_cutoff or peak_cutoff. Normalization is performed after cutoff.
percent_cutoff: cuts off when no more peaks contribute more than percent_cutoff to the total distribution. peak_cutoff: cuts off after that many peaks.
prefer_lowest_index controls the behavior if both percent_cutoff and peak_cutoff are specified. If true, then the lowest index found between the two methods will be used, otherwise the highest index.
all values will be fractional. normalize may be one of:
:total normalize to the total intensity :max normalize to the highest peak intensity :first normalize to the intensity of the first peak (this is typically the monoisotopic peak)
# File lib/mspire/isotope/distribution.rb, line 40 def isotope_distribution(normalize: Mspire::Isotope::Distribution::NORMALIZE, peak_cutoff: nil, percent_cutoff: nil, prefer_lowest_index: true, isotope_table: Mspire::Isotope::BY_ELEMENT) mono_dist = raw_isotope_distribution(isotope_table: isotope_table) cutoff_index = [ if percent_cutoff total_signal = mono_dist.reduce(:+) cutoff_index_less1 = (mono_dist.size-1).downto(0).find do |i| # finds the index (mono_dist[i] / total_signal) >= (percent_cutoff/100.0) end cutoff_index = cutoff_index_less1 ? (cutoff_index_less1 + 1) : 0 end, peak_cutoff ].compact.send( prefer_lowest_index ? :min : :max ) || mono_dist.size # mono_dist.size will result in nothing sliced off (i.e., for no cutoff) mono_dist.slice!(cutoff_index..-1) # normalization norm_by = case normalize when :total total_signal || mono_dist.reduce(:+) when :max mono_dist.max when :first mono_dist.first end mono_dist.map do |i| v = i / norm_by (v > 0) ? v : 0 end end
returns a spectrum object with mass values and intensity values. Arguments are passed directly to isotope_distribution. the molecule has a charge, this will be used to adjust the m/z values (by removing or adding electrons to the m/z and as the z)
# File lib/mspire/isotope/distribution.rb, line 79 def isotope_distribution_spectrum(*args) intensities = isotope_distribution(*args) mono = self.map {|el,cnt| Mspire::Mass::Element::MONO[el]*cnt }.reduce(:+) masses = Array.new(intensities.size) neutron = Mspire::Mass::NEUTRON masses[0] = mono (1...masses.size).each {|i| masses[i] = masses[i-1] + neutron } if self.charge && self.charge != 0 masses.map! do |mass| (mass - (self.charge * Mspire::Mass::ELECTRON)) / self.charge end end Mspire::Spectrum.new [masses, intensities] end
gives the monoisotopic mass adjusted by the current charge (i.e., adds/subtracts electron masses for the charges)
# File lib/mspire/molecular_formula.rb, line 120 def mass(consider_electron_masses = true) mss = inject(0.0) do |sum,(el,cnt)| sum + (Mspire::Mass::Element::MONO[el]*cnt) end mss -= (Mspire::Mass::ELECTRON * charge) if consider_electron_masses mss end
# File lib/mspire/molecular_formula.rb, line 90 def mul!(int, also_do_charge=true) raise ArgumentError, "must be an integer" unless int.is_a?(Integer) self.each do |k,v| self[k] = v * int end self.charge *= int if also_do_charge self end
returns nil if the charge == 0
# File lib/mspire/molecular_formula.rb, line 133 def mz(consider_electron_masses = true) if charge == 0 nil else mass(consider_electron_masses) / charge end end
returns relative ratios from low nominal mass to high nominal mass. These are not normalized at all.
# File lib/mspire/isotope/distribution.rb, line 96 def raw_isotope_distribution(isotope_table: Mspire::Isotope::BY_ELEMENT) low_nominal = 0 high_nominal = 0 self.each do |el,cnt| isotopes = isotope_table[el] low_nominal += (isotopes.first.mass_number * cnt) high_nominal += (isotopes.last.mass_number * cnt) end ffts = self.map do |el, cnt| isotope_el_ar = NArray.float(high_nominal+1) isotope_table[el].each do |isotope| isotope_el_ar[isotope.mass_number] = isotope.relative_abundance end FFTW3.fft(isotope_el_ar)**cnt end FFTW3.ifft(ffts.reduce(:*)).real.to_a[low_nominal..high_nominal] end
# File lib/mspire/molecular_formula.rb, line 70 def sub!(*others) others.each do |other| oth = other.dup self.each do |k,v| if oth.key?(k) self[k] -= oth.delete(k) end end oth.each do |k,v| self[k] = -v end self.charge -= other.charge end self end
# File lib/mspire/molecular_formula.rb, line 153 def to_hash Hash[ self ] end
# File lib/mspire/molecular_formula.rb, line 141 def to_s(alphabetize=true) h = alphabetize ? self.sort : self st = '' h.each do |k,v| if v > 0 st << k.to_s.capitalize st << v.to_s if v > 1 end end st end