Home  · Classes  · Annotated Classes  · Modules  · Members  · Namespaces  · Related Pages
SpectrumAlignment.h
Go to the documentation of this file.
1 // --------------------------------------------------------------------------
2 // OpenMS -- Open-Source Mass Spectrometry
3 // --------------------------------------------------------------------------
4 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
5 // ETH Zurich, and Freie Universitaet Berlin 2002-2017.
6 //
7 // This software is released under a three-clause BSD license:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of any author or any participating institution
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
16 // For a full list of authors, refer to the file AUTHORS.
17 // --------------------------------------------------------------------------
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
22 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // --------------------------------------------------------------------------
31 // $Maintainer: Timo Sachsenberg $
32 // $Authors: Andreas Bertsch $
33 // --------------------------------------------------------------------------
34 //
35 #ifndef OPENMS_COMPARISON_SPECTRA_SPECTRUMALIGNMENT_H
36 #define OPENMS_COMPARISON_SPECTRA_SPECTRUMALIGNMENT_H
37 
39 
40 #include <vector>
41 #include <map>
42 #include <utility>
43 #include <algorithm>
44 
45 #define ALIGNMENT_DEBUG
46 #undef ALIGNMENT_DEBUG
47 
48 namespace OpenMS
49 {
50 
66  class OPENMS_DLLAPI SpectrumAlignment :
67  public DefaultParamHandler
68  {
69 public:
70 
71  // @name Constructors and Destructors
72  // @{
75 
77  SpectrumAlignment(const SpectrumAlignment & source);
78 
80  virtual ~SpectrumAlignment();
81 
83  SpectrumAlignment & operator=(const SpectrumAlignment & source);
84  // @}
85 
86  template <typename SpectrumType1, typename SpectrumType2>
87  void getSpectrumAlignment(std::vector<std::pair<Size, Size> > & alignment, const SpectrumType1 & s1, const SpectrumType2 & s2) const
88  {
89  if (!s1.isSorted() || !s2.isSorted())
90  {
91  throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Input to SpectrumAlignment is not sorted!");
92  }
93 
94  // clear result
95  alignment.clear();
96  double tolerance = (double)param_.getValue("tolerance");
97 
98  if (!param_.getValue("is_relative_tolerance").toBool() )
99  {
100  std::map<Size, std::map<Size, std::pair<Size, Size> > > traceback;
101  std::map<Size, std::map<Size, double> > matrix;
102 
103  // init the matrix with "gap costs" tolerance
104  matrix[0][0] = 0;
105  for (Size i = 1; i <= s1.size(); ++i)
106  {
107  matrix[i][0] = i * tolerance;
108  traceback[i][0] = std::make_pair(i - 1, 0);
109  }
110  for (Size j = 1; j <= s2.size(); ++j)
111  {
112  matrix[0][j] = j * tolerance;
113  traceback[0][j] = std::make_pair(0, j - 1);
114  }
115 
116  // fill in the matrix
117  Size left_ptr(1);
118  Size last_i(0), last_j(0);
119 
120  //Size off_band_counter(0);
121  for (Size i = 1; i <= s1.size(); ++i)
122  {
123  double pos1(s1[i - 1].getMZ());
124 
125  for (Size j = left_ptr; j <= s2.size(); ++j)
126  {
127  bool off_band(false);
128  // find min of the three possible directions
129  double pos2(s2[j - 1].getMZ());
130  double diff_align = fabs(pos1 - pos2);
131 
132  // running off the right border of the band?
133  if (pos2 > pos1 && diff_align > tolerance)
134  {
135  if (i < s1.size() && j < s2.size() && s1[i].getMZ() < pos2)
136  {
137  off_band = true;
138  }
139  }
140 
141  // can we tighten the left border of the band?
142  if (pos1 > pos2 && diff_align > tolerance && j > left_ptr + 1)
143  {
144  ++left_ptr;
145  }
146 
147  double score_align = diff_align;
148 
149  if (matrix.find(i - 1) != matrix.end() && matrix[i - 1].find(j - 1) != matrix[i - 1].end())
150  {
151  score_align += matrix[i - 1][j - 1];
152  }
153  else
154  {
155  score_align += (i - 1 + j - 1) * tolerance;
156  }
157 
158  double score_up = tolerance;
159  if (matrix.find(i) != matrix.end() && matrix[i].find(j - 1) != matrix[i].end())
160  {
161  score_up += matrix[i][j - 1];
162  }
163  else
164  {
165  score_up += (i + j - 1) * tolerance;
166  }
167 
168  double score_left = tolerance;
169  if (matrix.find(i - 1) != matrix.end() && matrix[i - 1].find(j) != matrix[i - 1].end())
170  {
171  score_left += matrix[i - 1][j];
172  }
173  else
174  {
175  score_left += (i - 1 + j) * tolerance;
176  }
177 
178  #ifdef ALIGNMENT_DEBUG
179  cerr << i << " " << j << " " << left_ptr << " " << pos1 << " " << pos2 << " " << score_align << " " << score_left << " " << score_up << endl;
180  #endif
181 
182  if (score_align <= score_up && score_align <= score_left && diff_align <= tolerance)
183  {
184  matrix[i][j] = score_align;
185  traceback[i][j] = std::make_pair(i - 1, j - 1);
186  last_i = i;
187  last_j = j;
188  }
189  else
190  {
191  if (score_up <= score_left)
192  {
193  matrix[i][j] = score_up;
194  traceback[i][j] = std::make_pair(i, j - 1);
195  }
196  else
197  {
198  matrix[i][j] = score_left;
199  traceback[i][j] = std::make_pair(i - 1, j);
200  }
201  }
202 
203  if (off_band)
204  {
205  break;
206  }
207  }
208  }
209 
210  //last_i = s1.size() + 1;
211  //last_j = s2.size() + 1;
212 
213  //cerr << last_i << " " << last_j << endl;
214 
215  #ifdef ALIGNMENT_DEBUG
216  #if 0
217  cerr << "TheMatrix: " << endl << " \t \t";
218  for (Size j = 0; j != s2.size(); ++j)
219  {
220  cerr << s2[j].getPosition()[0] << " \t";
221  }
222  cerr << endl;
223  for (Size i = 0; i <= s1.size(); ++i)
224  {
225  if (i != 0)
226  {
227  cerr << s1[i - 1].getPosition()[0] << " \t";
228  }
229  else
230  {
231  cerr << " \t";
232  }
233  for (Size j = 0; j <= s2.size(); ++j)
234  {
235  if (matrix.has(i) && matrix[i].has(j))
236  {
237  if (traceback[i][j].first == i - 1 && traceback[i][j].second == j - 1)
238  {
239  cerr << "\\";
240  }
241  else
242  {
243  if (traceback[i][j].first == i - 1 && traceback[i][j].second == j)
244  {
245  cerr << "|";
246  }
247  else
248  {
249  cerr << "-";
250  }
251  }
252 
253  cerr << matrix[i][j] << " \t";
254  }
255  else
256  {
257  cerr << "-1 \t";
258  }
259  }
260  cerr << endl;
261  }
262  #endif
263  #endif
264 
265  // do traceback
266  Size i = last_i;
267  Size j = last_j;
268 
269  while (i >= 1 && j >= 1)
270  {
271  if (traceback[i][j].first == i - 1 && traceback[i][j].second == j - 1)
272  {
273  alignment.push_back(std::make_pair(i - 1, j - 1));
274  }
275  Size new_i = traceback[i][j].first;
276  Size new_j = traceback[i][j].second;
277 
278  i = new_i;
279  j = new_j;
280  }
281 
282  std::reverse(alignment.begin(), alignment.end());
283 
284  #ifdef ALIGNMENT_DEBUG
285  #if 0
286  // print alignment
287  cerr << "Alignment (size=" << alignment.size() << "): " << endl;
288 
289  Size i_s1(0), i_s2(0);
290  for (vector<pair<Size, Size> >::const_reverse_iterator it = alignment.rbegin(); it != alignment.rend(); ++it, ++i_s1, ++i_s2)
291  {
292  while (i_s1 < it->first - 1)
293  {
294  cerr << i_s1 << " " << s1[i_s1].getPosition()[0] << " " << s1[i_s1].getIntensity() << endl;
295  i_s1++;
296  }
297  while (i_s2 < it->second - 1)
298  {
299  cerr << " \t " << i_s2 << " " << s2[i_s2].getPosition()[0] << " " << s2[i_s2].getIntensity() << endl;
300  i_s2++;
301  }
302  cerr << "(" << s1[it->first - 1].getPosition()[0] << " <-> " << s2[it->second - 1].getPosition()[0] << ") ("
303  << it->first << "|" << it->second << ") (" << s1[it->first - 1].getIntensity() << "|" << s2[it->second - 1].getIntensity() << ")" << endl;
304  }
305  #endif
306  #endif
307  }
308  else // relative alignment (ppm tolerance)
309  {
310  for (Size i = 0; i != s1.size(); ++i)
311  {
312  const double& theo_mz = s1[i].getMZ();
313  double max_dist_dalton = theo_mz * tolerance * 1e-6;
314 
315  // iterate over peaks in experimental spectrum in given fragment tolerance around theoretical peak
316  Size j = s2.findNearest(theo_mz);
317  double exp_mz = s2[j].getMZ();
318 
319  // found peak match
320  if (std::abs(theo_mz - exp_mz) < max_dist_dalton)
321  {
322  alignment.push_back(std::make_pair(i, j));
323  }
324  }
325  }
326  }
327  };
328 }
329 #endif //OPENMS_COMPARISON_SPECTRA_SPECTRUMALIGNMENT_H
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:47
A method or algorithm argument contains illegal values.
Definition: Exception.h:649
void getSpectrumAlignment(std::vector< std::pair< Size, Size > > &alignment, const SpectrumType1 &s1, const SpectrumType2 &s2) const
Definition: SpectrumAlignment.h:87
Aligns the peaks of two sorted spectra Method 1: Using a banded (width via &#39;tolerance&#39; parameter) ali...
Definition: SpectrumAlignment.h:66
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition: Types.h:128
A base class for all classes handling default parameters.
Definition: DefaultParamHandler.h:92

OpenMS / TOPP release 2.3.0 Documentation generated on Tue Jan 9 2018 18:22:04 using doxygen 1.8.13