princelab/mspire

View on GitHub
lib/mspire/ident/pepxml/search_hit.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'set'
require 'merge'
require 'nokogiri'

module Mspire ; end
module Mspire::Ident ; end


class Mspire::Ident::Pepxml 

  class Mspire::Ident::Pepxml::SearchHit 
    include Merge

    DEFAULT_MEMBERS = [:hit_rank, :peptide, :peptide_prev_aa, :peptide_next_aa, :num_matched_ions, :tot_num_ions, :calc_neutral_pep_mass, :massdiff, :num_tol_term, :num_missed_cleavages, :is_rejected, :protein, :num_tot_proteins, :protein_desc, :calc_pI, :protein_mw, :modification_info, :search_scores, :spectrum_query]

    Required = Set.new([:hit_rank, :peptide, :protein, :num_tot_proteins, :calc_neutral_pep_mass, :massdiff])

    class << self
      attr_writer :members
      def members
        @members || DEFAULT_MEMBERS
      end
    end

    members.each {|memb| attr_accessor memb }

    # rank of the peptide hit (required)
    attr_accessor :hit_rank
    # Peptide aminoacid sequence (with no indicated modifications) (required)
    attr_accessor :peptide

    # Aminoacid preceding peptide ('-' if none)
    attr_accessor :peptide_prev_aa

    # Aminoacid following peptide (- if none)
    attr_accessor :peptide_next_aa

    # Number of peptide fragment ions found in spectrum (Integer)
    attr_accessor :num_matched_ions

    # Number of peptide fragment ions predicted for peptide (Integer)
    attr_accessor :tot_num_ions

    # (required)
    attr_accessor :calc_neutral_pep_mass

    # Mass(precursor ion) - Mass(peptide) (required)
    attr_accessor :massdiff

    # Number of peptide termini consistent with cleavage by sample enzyme
    attr_accessor :num_tol_term

    # Number of sample enzyme cleavage sites internal to peptide<
    attr_accessor :num_missed_cleavages

    # Potential use in future for user manual validation (true/false)
    # by default, this will be set to false
    # (the xml is expressed as a 0 or 1)
    attr_accessor :is_rejected

    # a protein identifier string (required)
    attr_accessor :protein

    # Number of unique proteins in search database containing peptide
    # (required)
    attr_accessor :num_tot_proteins

    # Extracted from search database
    attr_accessor :protein_desc

    attr_accessor :calc_pI
    attr_accessor :protein_mw

    # a ModificationInfo object
    attr_accessor :modification_info

    # a Hash with keys (the score type) and values
    # (to_xml calls each_pair to generate the xml, so a Struct would also
    # work)
    attr_accessor :search_scores

    # a link back to the spectrum_query object
    attr_accessor :spectrum_query


    Non_standard_amino_acid_char_re = %r{[^A-Z\.\-]}

    alias_method :aaseq, :peptide
    alias_method :aaseq=, :peptide=

    # takes either a hash or an ordered list of values to set.
    # yeilds an empty search_scores hash if given a block.
    # mind that you set the ModificationInfo object as needed.
    def initialize(*args, &block)
      @search_scores = {}
      if args.first.is_a?(Hash)
        merge!(args.first)
      else
        self.class.members.zip(args) do |k,v|
          send("#{k}=", v)
        end
      end
      block.call(@search_scores) if block
    end

    def members
      self.class.members
    end

    def to_xml(builder=nil)
      xmlb = builder || Nokogiri::XML::Builder.new
      attrs = members[0,14].map {|k| v=send(k) ; [k, v] if v }.compact
      hash_attrs = Hash[attrs]
      hash_attrs[:massdiff] = hash_attrs[:massdiff].to_plus_minus_string
      xmlb.search_hit(hash_attrs) do |xmlb|
        @modification_info.to_xml(xmlb) if @modification_info
        @search_scores.each_pair {|k,v| xmlb.search_score(:name => k, :value => v) }
      end
      builder || xmlb.doc.root.to_xml
    end

    def from_pepxml_node(node)
      node.attributes
      self[0] = node['hit_rank'].to_i
      self[1] = node['peptide']
      self[2] = node['peptide_prev_aa']
      self[3] = node['peptide_next_aa']
      self[4] = node['protein']  ## will this be the string?? (yes, for now)
      self[5] = node['num_tot_proteins'].to_i
      self[6] = node['num_matched_ions'].to_i
      self[7] = node['tot_num_ions'].to_i
      self[8] = node['calc_neutral_pep_mass'].to_f
      self[9] = node['massdiff'].to_f
      self[10] = node['num_tol_term'].to_i
      self[11] = node['num_missed_cleavages'].to_i
      self[12] = node['is_rejected'].to_i
      self
    end

    Simple = Struct.new(:id, :search, :aaseq, :charge, :search_scores, :analysis_results)
  end

end