Module: Ms::Spectrum::Compare

Included in:
Ms::Spectrum
Defined in:
lib/ms/spectrum/compare.rb

Instance Method Summary collapse

Instance Method Details

#compare(other, opts = {}) ⇒ Object

opts == :mutual_best

will only return intensities on mutual best matches within radius.
yields [self_intensity, other_intensity] for each match within
the radius.

opts == :best

yields the best match in the radius peak.  If one peak is already
spoken for, a different peak may still match a close peak if it is
its best match (how to explain this?).

if opts == true then returns […, diff] (d: true) if opts == true then returns [mz, mz, int, int] (d: false) if opts == true then returns [i,j] (d: false) assumes mzs are increasing



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/ms/spectrum/compare.rb', line 84

def compare(other, opts={})
  defaults = {:radius => 1.0, :type=>:mutual_best, :yield_diff => true, :yield_mz => false, :yield_indices => false}
  (radius, type, yield_diff, yield_mz, yield_indices) = defaults.merge(opts).values_at(:radius, :type, :yield_diff, :yield_mz, :yield_indices)
  blk = block_given?
  output = [] if !blk
  s_ints = self.intensities
  s_size = self.mzs.size
  o_mzs = other.mzs
  o_size = o_mzs.size
  o_ints = other.intensities
  oi = 0
  start_j = 0
  save = []
  self.mzs.each_with_index do |mz,i|
    break if start_j >= o_size
    hi = mz + radius
    lo = mz - radius
    start_j.upto(o_size-1) do |j|
      diff = mz - o_mzs[j]
      absdiff = diff.abs
      if absdiff <= radius  # a potential hit!
        save << [absdiff, i, j]
      elsif diff < 0  # we overshot
        break  
      else  # undershot
        start_j = j + 1  # this is for the benefit of the next search
      end
    end
  end

  #puts "BEFORE SORT: "
  #p save
  #save.sort!
  #puts "AFTER SORT: "
  #p save
  iset = Array.new(s_size)
  jset = Array.new(o_size)
  save.each do |diff, i, j|
    unless iset[i] || jset[j]
      if type == :best
        iset[i] = true
        jset[j] = true
      end
      to_ret = 
        if yield_indices
          [i,j]
        else
          [s_ints[i], o_ints[j]]
        end
      if yield_mz
        to_ret.unshift( s_mzs[i], o_mzs[j] )
      end
      if yield_diff
        to_ret.push( diff )
      end
      if blk
        yield to_ret
      else
        output << to_ret
      end
    end
    if type == :mutual_best
      iset[i] = true
      jset[j] = true
    end
  end
  output
end

#pic_score(other, opts = {}) ⇒ Object

percent ion current score: the percent of total ion current of the calling object that can be explained by other. Ranges from 0-100



23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/ms/spectrum/compare.rb', line 23

def pic_score(other, opts={})
  opts= {:normalize => true}.merge(opts)
  (a_spec, b_spec) = 
    if opts[:normalize] == true
      [self.normalize, other.normalize]
    else
      [self, other]
    end
  overlapping_current = 0.0
  a_spec.compare(b_spec, opts.merge( {:yield_diff => false} )) do |sint, oint|
    overlapping_current += [oint, sint].min
  end
  100.0 * (overlapping_current / a_spec.intensities.sum)
end

#sim_score(other, opts = {}) ⇒ Object

Zhang Analytical Chemistry. 2004 76(14) “the ratio between the sum of geometric mean and sum of arithmetic mean of all ions, after the two spectra are normalized to the same total ion intensity” The score will be 1 for identical spectra (Σ (Ii*Ij)^½) / (ΣIi * ΣIj)^½

options:

:normalize => true | false (d: true) normalizes intensities first

relevant options given for ‘compare’ will be passed through:

:radius
:type


54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/ms/spectrum/compare.rb', line 54

def sim_score(other, opts={})
  opts = {:normalize => true}.merge(opts)
  (a_spec, b_spec) = 
    if opts[:normalize] == true
      [self.normalize, other.normalize]
    else
      [self, other]
    end
  numer = 0.0
  
  a_spec.compare(b_spec, opts.merge( {:yield_diff => false} )) do |sint, oint|
    numer += Math.sqrt(sint * oint)
  end
  numer / Math.sqrt( a_spec.intensities.sum * b_spec.intensities.sum )
end