Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef OPENMS_FILTERING_TRANSFORMERS_SPECTRAMERGER_H
00036 #define OPENMS_FILTERING_TRANSFORMERS_SPECTRAMERGER_H
00037
00038 #include <OpenMS/DATASTRUCTURES/DefaultParamHandler.h>
00039 #include <OpenMS/COMPARISON/CLUSTERING/CompleteLinkage.h>
00040 #include <OpenMS/COMPARISON/CLUSTERING/SingleLinkage.h>
00041 #include <OpenMS/COMPARISON/CLUSTERING/ClusterAnalyzer.h>
00042 #include <OpenMS/COMPARISON/CLUSTERING/ClusterHierarchical.h>
00043 #include <OpenMS/COMPARISON/SPECTRA/SpectrumAlignment.h>
00044 #include <OpenMS/KERNEL/StandardTypes.h>
00045 #include <OpenMS/KERNEL/RangeUtils.h>
00046 #include <OpenMS/KERNEL/BaseFeature.h>
00047 #include <OpenMS/CONCEPT/LogStream.h>
00048 #include <vector>
00049
00050 namespace OpenMS
00051 {
00052
00061 class OPENMS_DLLAPI SpectraMerger :
00062 public DefaultParamHandler
00063 {
00064
00065 protected:
00066
00067
00068
00069
00070
00071
00072
00073
00074 class SpectraDistance_ :
00075 public DefaultParamHandler
00076 {
00077 public:
00078 SpectraDistance_() :
00079 DefaultParamHandler("SpectraDistance")
00080 {
00081 defaults_.setValue("rt_tolerance", 10.0, "Maximal RT distance (in [s]) for two spectra's precursors.");
00082 defaults_.setValue("mz_tolerance", 1.0, "Maximal m/z distance (in Da) for two spectra's precursors.");
00083 defaultsToParam_();
00084 }
00085
00086 void updateMembers_()
00087 {
00088 rt_max_ = (DoubleReal) param_.getValue("rt_tolerance");
00089 mz_max_ = (DoubleReal) param_.getValue("mz_tolerance");
00090
00091 return;
00092 }
00093
00094 double getSimilarity(const DoubleReal d_rt, const DoubleReal d_mz) const
00095 {
00096
00097 return 1 - ((d_rt / rt_max_ + d_mz / mz_max_) / 2);
00098 }
00099
00100
00101 double operator()(const BaseFeature & first, const BaseFeature & second) const
00102 {
00103
00104 DoubleReal d_rt = fabs(first.getRT() - second.getRT());
00105 DoubleReal d_mz = fabs(first.getMZ() - second.getMZ());
00106
00107 if (d_rt > rt_max_ || d_mz > mz_max_) {return 0; }
00108
00109
00110 DoubleReal sim = getSimilarity(d_rt, d_mz);
00111
00112 return sim;
00113 }
00114
00115 protected:
00116 DoubleReal rt_max_;
00117 DoubleReal mz_max_;
00118
00119 };
00120
00121 public:
00122
00124 typedef Map<Size, std::vector<Size> > MergeBlocks;
00125
00126
00127
00129 SpectraMerger();
00130
00132 SpectraMerger(const SpectraMerger & source);
00133
00135 virtual ~SpectraMerger();
00136
00137
00138
00139
00141 SpectraMerger & operator=(const SpectraMerger & source);
00142
00143
00144
00145
00147 template <typename MapType>
00148 void mergeSpectraBlockWise(MapType & exp)
00149 {
00150 IntList ms_levels = (IntList) (param_.getValue("block_method:ms_levels"));
00151 Int rt_block_size(param_.getValue("block_method:rt_block_size"));
00152 DoubleReal rt_max_length = (param_.getValue("block_method:rt_max_length"));
00153
00154 if (rt_max_length == 0)
00155 {
00156 rt_max_length = (std::numeric_limits<DoubleReal>::max)();
00157 }
00158
00159 for (IntList::iterator it_mslevel = ms_levels.begin(); it_mslevel < ms_levels.end(); ++it_mslevel)
00160 {
00161 MergeBlocks spectra_to_merge;
00162 Size idx_block(0);
00163 SignedSize block_size_count(rt_block_size + 1);
00164 Size idx_spectrum(0);
00165 for (typename MapType::const_iterator it1 = exp.begin(); it1 != exp.end(); ++it1)
00166 {
00167 if (Int(it1->getMSLevel()) == *it_mslevel)
00168 {
00169
00170 if (++block_size_count >= rt_block_size ||
00171 exp[idx_spectrum].getRT() - exp[idx_block].getRT() > rt_max_length)
00172 {
00173 block_size_count = 0;
00174 idx_block = idx_spectrum;
00175 }
00176 else
00177 {
00178 spectra_to_merge[idx_block].push_back(idx_spectrum);
00179 }
00180 }
00181
00182 ++idx_spectrum;
00183 }
00184
00185 if (block_size_count == 0)
00186 {
00187 spectra_to_merge[idx_block] = std::vector<Size>();
00188 }
00189
00190
00191 mergeSpectra_(exp, spectra_to_merge, *it_mslevel);
00192 }
00193
00194 exp.sortSpectra();
00195
00196 return;
00197 }
00198
00200 template <typename MapType>
00201 void mergeSpectraPrecursors(MapType & exp)
00202 {
00203
00204
00205 Size data_size;
00206 std::vector<BinaryTreeNode> tree;
00207 Map<Size, Size> index_mapping;
00208
00209 {
00210 std::vector<BaseFeature> data;
00211
00212 for (Size i = 0; i < exp.size(); ++i)
00213 {
00214 if (exp[i].getMSLevel() != 2) continue;
00215
00216
00217 index_mapping[data.size()] = i;
00218
00219
00220 BaseFeature bf;
00221 bf.setRT(exp[i].getRT());
00222 std::vector<Precursor> pcs = exp[i].getPrecursors();
00223 if (pcs.empty()) throw Exception::MissingInformation(__FILE__, __LINE__, __PRETTY_FUNCTION__, String("Scan #") + String(i) + " does not contain any precursor information! Unable to cluster!");
00224 if (pcs.size() > 1) LOG_WARN << "More than one precursor found. Using first one!" << std::endl;
00225 bf.setMZ(pcs[0].getMZ());
00226 data.push_back(bf);
00227 }
00228 data_size = data.size();
00229
00230 SpectraDistance_ llc;
00231 llc.setParameters(param_.copy("precursor_method:", true));
00232 SingleLinkage sl;
00233 DistanceMatrix<Real> dist;
00234 ClusterHierarchical ch;
00235
00236
00237
00238 ch.cluster<BaseFeature, SpectraDistance_>(data, llc, sl, tree, dist);
00239 }
00240
00241
00242 ClusterAnalyzer ca;
00243 std::vector<std::vector<Size> > clusters;
00244
00245 Size node_count = 0;
00246 for (Size ii = 0; ii < tree.size(); ++ii)
00247 {
00248 if (tree[ii].distance >= 1) tree[ii].distance = -1;
00249 if (tree[ii].distance != -1) ++node_count;
00250 }
00251 ca.cut(data_size - node_count, tree, clusters);
00252
00253
00254
00255
00256
00257 MergeBlocks spectra_to_merge;
00258
00259 for (Size i_outer = 0; i_outer < clusters.size(); ++i_outer)
00260 {
00261 if (clusters[i_outer].size() <= 1) continue;
00262
00263 Size cl_index0 = clusters[i_outer][0];
00264 spectra_to_merge[index_mapping[cl_index0]] = std::vector<Size>();
00265
00266 for (Size i_inner = 1; i_inner < clusters[i_outer].size(); ++i_inner)
00267 {
00268 Size cl_index = clusters[i_outer][i_inner];
00269 spectra_to_merge[index_mapping[cl_index0]].push_back(index_mapping[cl_index]);
00270 }
00271 }
00272
00273
00274 mergeSpectra_(exp, spectra_to_merge, 2);
00275
00276 exp.sortSpectra();
00277
00278 return;
00279 }
00280
00281
00282
00283 protected:
00284
00295 template <typename MapType>
00296 void mergeSpectra_(MapType & exp, const MergeBlocks & spectra_to_merge, const UInt ms_level)
00297 {
00298 DoubleReal mz_binning_width(param_.getValue("mz_binning_width"));
00299 String mz_binning_unit(param_.getValue("mz_binning_width_unit"));
00300
00301
00302 MapType merged_spectra;
00303
00304 Map<Size, Size> cluster_sizes;
00305 std::set<Size> merged_indices;
00306
00307
00308 SpectrumAlignment sas;
00309 Param p;
00310 p.setValue("tolerance", mz_binning_width);
00311 if (!(mz_binning_unit == "Da" || mz_binning_unit == "ppm")) throw Exception::IllegalSelfOperation(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00312 p.setValue("is_relative_tolerance", mz_binning_unit == "Da" ? "false" : "true");
00313 sas.setParameters(p);
00314 std::vector<std::pair<Size, Size> > alignment;
00315
00316 Size count_peaks_aligned(0);
00317 Size count_peaks_overall(0);
00318
00319
00320 for (Map<Size, std::vector<Size> >::ConstIterator it = spectra_to_merge.begin(); it != spectra_to_merge.end(); ++it)
00321 {
00322
00323 ++cluster_sizes[it->second.size() + 1];
00324
00325 typename MapType::SpectrumType consensus_spec = exp[it->first];
00326 consensus_spec.setMSLevel(ms_level);
00327
00328
00329 merged_indices.insert(it->first);
00330
00331
00332 DoubleReal rt_average = consensus_spec.getRT();
00333 DoubleReal precursor_mz_average = 0.0;
00334 Size precursor_count(0);
00335 if (!consensus_spec.getPrecursors().empty())
00336 {
00337 precursor_mz_average = consensus_spec.getPrecursors()[0].getMZ();
00338 ++precursor_count;
00339 }
00340
00341 count_peaks_overall += consensus_spec.size();
00342
00343
00344 for (std::vector<Size>::const_iterator sit = it->second.begin(); sit != it->second.end(); ++sit)
00345 {
00346 consensus_spec.unify(exp[*sit]);
00347 merged_indices.insert(*sit);
00348
00349 rt_average += exp[*sit].getRT();
00350 if (ms_level >= 2 && exp[*sit].getPrecursors().size() > 0)
00351 {
00352 precursor_mz_average += exp[*sit].getPrecursors()[0].getMZ();
00353 ++precursor_count;
00354 }
00355
00356
00357 sas.getSpectrumAlignment(alignment, consensus_spec, exp[*sit]);
00358
00359 count_peaks_aligned += alignment.size();
00360 count_peaks_overall += exp[*sit].size();
00361
00362 Size align_index(0);
00363 Size spec_b_index(0);
00364
00365
00366 Size spec_a = consensus_spec.size(), spec_b = exp[*sit].size(), align_size = alignment.size();
00367 for (typename MapType::SpectrumType::ConstIterator pit = exp[*sit].begin(); pit != exp[*sit].end(); ++pit)
00368 {
00369
00370 if (alignment.size() > 0 && alignment[align_index].second == spec_b_index)
00371 {
00372 consensus_spec[alignment[align_index].first].setIntensity(consensus_spec[alignment[align_index].first].getIntensity() +
00373 pit->getIntensity());
00374 ++align_index;
00375 if (align_index == alignment.size()) alignment.clear();
00376 }
00377 else
00378 {
00379 consensus_spec.push_back(*pit);
00380 }
00381 ++spec_b_index;
00382 }
00383 consensus_spec.sortByPosition();
00384 if (spec_a + spec_b - align_size != consensus_spec.size()) std::cerr << "\n\n ERRROR \n\n";
00385 }
00386 rt_average /= it->second.size() + 1;
00387 consensus_spec.setRT(rt_average);
00388
00389 if (ms_level >= 2)
00390 {
00391 if (precursor_count) precursor_mz_average /= precursor_count;
00392 std::vector<Precursor> pcs = consensus_spec.getPrecursors();
00393
00394 pcs.resize(1);
00395 pcs[0].setMZ(precursor_mz_average);
00396 consensus_spec.setPrecursors(pcs);
00397 }
00398
00399 if (consensus_spec.empty()) continue;
00400 else merged_spectra.push_back(consensus_spec);
00401 }
00402
00403 LOG_INFO << "Cluster sizes:\n";
00404 for (Map<Size, Size>::const_iterator it = cluster_sizes.begin(); it != cluster_sizes.end(); ++it)
00405 {
00406 LOG_INFO << " size " << it->first << ": " << it->second << "x\n";
00407 }
00408
00409 char buffer[200];
00410 sprintf(buffer, "%d/%d (%.2f %%) of blocked spectra", (int)count_peaks_aligned,
00411 (int)count_peaks_overall, float(count_peaks_aligned) / float(count_peaks_overall) * 100.);
00412 LOG_INFO << "Number of merged peaks: " << String(buffer) << "\n";
00413
00414
00415 typename MapType::SpectrumType empty_spec;
00416 MapType exp_tmp;
00417 for (Size i = 0; i < exp.size(); ++i)
00418 {
00419 if (merged_indices.count(i) == 0)
00420 {
00421 exp_tmp.push_back(exp[i]);
00422 exp[i] = empty_spec;
00423 }
00424 }
00425 typedef std::vector<typename MapType::SpectrumType> Base;
00426 exp.Base::operator=(exp_tmp);
00427
00428
00429
00430
00431 exp.insert(exp.end(), merged_spectra.begin(), merged_spectra.end());
00432
00433 }
00434
00435 };
00436
00437 }
00438 #endif //OPENMS_FILTERING_TRANSFORMERS_SPECTRAMERGER_H