Home  · Classes  · Annotated Classes  · Modules  · Members  · Namespaces  · Related Pages

MSExperiment.h

Go to the documentation of this file.
00001 // --------------------------------------------------------------------------
00002 //                   OpenMS -- Open-Source Mass Spectrometry
00003 // --------------------------------------------------------------------------
00004 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
00005 // ETH Zurich, and Freie Universitaet Berlin 2002-2012.
00006 //
00007 // This software is released under a three-clause BSD license:
00008 //  * Redistributions of source code must retain the above copyright
00009 //    notice, this list of conditions and the following disclaimer.
00010 //  * Redistributions in binary form must reproduce the above copyright
00011 //    notice, this list of conditions and the following disclaimer in the
00012 //    documentation and/or other materials provided with the distribution.
00013 //  * Neither the name of any author or any participating institution
00014 //    may be used to endorse or promote products derived from this software
00015 //    without specific prior written permission.
00016 // For a full list of authors, refer to the file AUTHORS.
00017 // --------------------------------------------------------------------------
00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
00022 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00024 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00025 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00027 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00028 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 //
00030 // --------------------------------------------------------------------------
00031 // $Maintainer: Stephan Aiche$
00032 // $Authors: Marc Sturm $
00033 // --------------------------------------------------------------------------
00034 
00035 #ifndef OPENMS_KERNEL_MSEXPERIMENT_H
00036 #define OPENMS_KERNEL_MSEXPERIMENT_H
00037 
00038 #include <OpenMS/KERNEL/MSSpectrum.h>
00039 #include <OpenMS/KERNEL/MSChromatogram.h>
00040 #include <OpenMS/METADATA/ExperimentalSettings.h>
00041 #include <OpenMS/DATASTRUCTURES/DRange.h>
00042 #include <OpenMS/FORMAT/DB/PersistentObject.h>
00043 #include <OpenMS/CONCEPT/Exception.h>
00044 #include <OpenMS/KERNEL/AreaIterator.h>
00045 
00046 #include <vector>
00047 #include <algorithm>
00048 #include <limits>
00049 
00050 namespace OpenMS
00051 {
00052   class Peak1D;
00053 
00067   template <typename PeakT = Peak1D, typename ChromatogramPeakT = ChromatogramPeak>
00068   class MSExperiment :
00069     public std::vector<MSSpectrum<PeakT> >,
00070     public RangeManager<2>,
00071     public ExperimentalSettings,
00072     public PersistentObject
00073   {
00074 public:
00076 
00077 
00078     typedef PeakT PeakType;
00080     typedef ChromatogramPeakT ChromatogramPeakType;
00082     typedef DRange<2> AreaType;
00084     typedef typename PeakType::CoordinateType CoordinateType;
00086     typedef typename PeakType::IntensityType IntensityType;
00088     typedef RangeManager<2> RangeManagerType;
00090     typedef MSSpectrum<PeakType> SpectrumType;
00092     typedef MSChromatogram<ChromatogramPeakType> ChromatogramType;
00094     typedef std::vector<SpectrumType> Base;
00096 
00098 
00099 
00100     typedef typename std::vector<SpectrumType>::iterator Iterator;
00102     typedef typename std::vector<SpectrumType>::const_iterator ConstIterator;
00104     typedef Internal::AreaIterator<PeakT, PeakT &, PeakT *, Iterator, typename SpectrumType::Iterator> AreaIterator;
00106     typedef Internal::AreaIterator<const PeakT, const PeakT &, const PeakT *, ConstIterator, typename SpectrumType::ConstIterator> ConstAreaIterator;
00108 
00110     MSExperiment() :
00111       Base(),
00112       RangeManagerType(),
00113       ExperimentalSettings(),
00114       PersistentObject(),
00115       ms_levels_(),
00116       total_size_(0)
00117     {}
00118 
00120     MSExperiment(const MSExperiment & source) :
00121       std::vector<MSSpectrum<PeakT> >(source),
00122       RangeManagerType(source),
00123       ExperimentalSettings(source),
00124       PersistentObject(source),
00125       ms_levels_(source.ms_levels_),
00126       total_size_(source.total_size_),
00127       chromatograms_(source.chromatograms_)
00128     {}
00129 
00131     MSExperiment & operator=(const MSExperiment & source)
00132     {
00133       if (&source == this) return *this;
00134 
00135       Base::operator=(source);
00136       RangeManagerType::operator=(source);
00137       ExperimentalSettings::operator=(source);
00138       PersistentObject::operator=(source);
00139 
00140       ms_levels_     = source.ms_levels_;
00141       total_size_    = source.total_size_;
00142       chromatograms_ = source.chromatograms_;
00143 
00144       //no need to copy the alloc?!
00145       //alloc_
00146 
00147       return *this;
00148     }
00149 
00151     MSExperiment & operator=(const ExperimentalSettings & source)
00152     {
00153       ExperimentalSettings::operator=(source);
00154       return *this;
00155     }
00156 
00158     bool operator==(const MSExperiment & rhs) const
00159     {
00160       return ExperimentalSettings::operator==(rhs) && std::operator==(rhs, *this) && chromatograms_ == rhs.chromatograms_;
00161     }
00162 
00164     bool operator!=(const MSExperiment & rhs) const
00165     {
00166       return !(operator==(rhs));
00167     }
00168 
00170 
00171 
00177     template <class Container>
00178     void get2DData(Container & cont) const
00179     {
00180       for (typename Base::const_iterator spec = Base::begin(); spec != Base::end(); ++spec)
00181       {
00182         if (spec->getMSLevel() != 1)
00183         {
00184           continue;
00185         }
00186         for (typename SpectrumType::const_iterator it = spec->begin(); it != spec->end(); ++it)
00187         {
00188           cont.push_back(typename Container::value_type());
00189           cont.back().setRT(spec->getRT());
00190           cont.back().setMZ(it->getMZ());
00191           cont.back().setIntensity(it->getIntensity());
00192         }
00193       }
00194     }
00195 
00204     template <class Container>
00205     void set2DData(const Container & cont)
00206     {
00207       SpectrumType * spectrum = 0;
00208       // If the container is empty, nothing will happen
00209       if (cont.empty()) return;
00210 
00211       typename PeakType::CoordinateType current_rt = -(std::numeric_limits<typename PeakType::CoordinateType>::max)();
00212 
00213       for (typename Container::const_iterator iter = cont.begin(); iter != cont.end(); ++iter)
00214       {
00215         // check if the retention time time has changed
00216         if (current_rt != iter->getRT() || spectrum == 0)
00217         {
00218           if (current_rt > iter->getRT())
00219           {
00220             throw Exception::Precondition(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Input container is not sorted!");
00221           }
00222           current_rt =  iter->getRT();
00223           Base::insert(Base::end(), SpectrumType());
00224           spectrum = &(Base::back());
00225           spectrum->setRT(current_rt);
00226           spectrum->setMSLevel(1);
00227         }
00228 
00229         // create temporary peak and insert it into spectrum
00230         spectrum->insert(spectrum->end(), PeakType());
00231         spectrum->back().setIntensity(iter->getIntensity());
00232         spectrum->back().setPosition(iter->getMZ());
00233       }
00234     }
00235 
00237 
00239 
00240 
00241     AreaIterator areaBegin(CoordinateType min_rt, CoordinateType max_rt, CoordinateType min_mz, CoordinateType max_mz)
00242     {
00243       OPENMS_PRECONDITION(min_rt <= max_rt, "Swapped RT range boundaries!")
00244       OPENMS_PRECONDITION(min_mz <= max_mz, "Swapped MZ range boundaries!")
00245       //std::cout << "areaBegin: " << min_rt << " " << max_rt << " " << min_mz << " " << max_mz << std::endl;
00246       return AreaIterator(this->begin(), RTBegin(min_rt), RTEnd(max_rt), min_mz, max_mz);
00247     }
00248 
00250     AreaIterator areaEnd()
00251     {
00252       return AreaIterator();
00253     }
00254 
00256     ConstAreaIterator areaBeginConst(CoordinateType min_rt, CoordinateType max_rt, CoordinateType min_mz, CoordinateType max_mz) const
00257     {
00258       OPENMS_PRECONDITION(min_rt <= max_rt, "Swapped RT range boundaries!")
00259       OPENMS_PRECONDITION(min_mz <= max_mz, "Swapped MZ range boundaries!")
00260       //std::cout << "areaBeginConst: " << min_rt << " " << max_rt << " " << min_mz << " " << max_mz << std::endl;
00261       return ConstAreaIterator(this->begin(), RTBegin(min_rt), RTEnd(max_rt), min_mz, max_mz);
00262     }
00263 
00265     ConstAreaIterator areaEndConst() const
00266     {
00267       return ConstAreaIterator();
00268     }
00269 
00277     ConstIterator RTBegin(CoordinateType rt) const
00278     {
00279       SpectrumType s;
00280       s.setRT(rt);
00281       return lower_bound(Base::begin(), Base::end(), s, typename SpectrumType::RTLess());
00282     }
00283 
00291     ConstIterator RTEnd(CoordinateType rt) const
00292     {
00293       SpectrumType s;
00294       s.setRT(rt);
00295       return upper_bound(Base::begin(), Base::end(), s, typename SpectrumType::RTLess());
00296     }
00297 
00303     Iterator RTBegin(CoordinateType rt)
00304     {
00305       SpectrumType s;
00306       s.setRT(rt);
00307       return lower_bound(Base::begin(), Base::end(), s, typename SpectrumType::RTLess());
00308     }
00309 
00315     Iterator RTEnd(CoordinateType rt)
00316     {
00317       SpectrumType s;
00318       s.setRT(rt);
00319       return upper_bound(Base::begin(), Base::end(), s, typename SpectrumType::RTLess());
00320     }
00321 
00323 
00329 
00330     // Docu in base class
00331     virtual void updateRanges()
00332     {
00333       updateRanges(-1);
00334     }
00335 
00341     void updateRanges(Int ms_level)
00342     {
00343       //clear MS levels
00344       ms_levels_.clear();
00345 
00346       //reset mz/rt/int range
00347       this->clearRanges();
00348       //reset point count
00349       total_size_ = 0;
00350 
00351       //empty
00352       if (this->size() == 0 && chromatograms_.empty())
00353       {
00354         return;
00355       }
00356 
00357       //update
00358       for (typename Base::iterator it = this->begin(); it != this->end(); ++it)
00359       {
00360         if (ms_level < Int(0) || Int(it->getMSLevel()) == ms_level)
00361         {
00362           //ms levels
00363           if (std::find(ms_levels_.begin(), ms_levels_.end(), it->getMSLevel()) == ms_levels_.end())
00364           {
00365             ms_levels_.push_back(it->getMSLevel());
00366           }
00367 
00368           // calculate size
00369           total_size_ += it->size();
00370 
00371           //rt
00372           if (it->getRT() < RangeManagerType::pos_range_.minX()) RangeManagerType::pos_range_.setMinX(it->getRT());
00373           if (it->getRT() > RangeManagerType::pos_range_.maxX()) RangeManagerType::pos_range_.setMaxX(it->getRT());
00374 
00375           //do not update mz and int when the spectrum is empty
00376           if (it->size() == 0) continue;
00377 
00378           it->updateRanges();
00379 
00380           //mz
00381           if (it->getMin()[0] < RangeManagerType::pos_range_.minY()) RangeManagerType::pos_range_.setMinY(it->getMin()[0]);
00382           if (it->getMax()[0] > RangeManagerType::pos_range_.maxY()) RangeManagerType::pos_range_.setMaxY(it->getMax()[0]);
00383 
00384           //int
00385           if (it->getMinInt() < RangeManagerType::int_range_.minX()) RangeManagerType::int_range_.setMinX(it->getMinInt());
00386           if (it->getMaxInt() > RangeManagerType::int_range_.maxX()) RangeManagerType::int_range_.setMaxX(it->getMaxInt());
00387 
00388         }
00389         // for MS level = 1 we extend the range for all the MS2 precursors
00390         if (ms_level == 1 && it->getMSLevel() == 2)
00391         {
00392           if (!it->getPrecursors().empty())
00393           {
00394             DoubleReal pc_rt = it->getRT();
00395             if (pc_rt < RangeManagerType::pos_range_.minX()) RangeManagerType::pos_range_.setMinX(pc_rt);
00396             if (pc_rt > RangeManagerType::pos_range_.maxX()) RangeManagerType::pos_range_.setMaxX(pc_rt);
00397             DoubleReal pc_mz = it->getPrecursors()[0].getMZ();
00398             if (pc_mz < RangeManagerType::pos_range_.minY()) RangeManagerType::pos_range_.setMinY(pc_mz);
00399             if (pc_mz > RangeManagerType::pos_range_.maxY()) RangeManagerType::pos_range_.setMaxY(pc_mz);
00400           }
00401 
00402         }
00403 
00404       }
00405       std::sort(ms_levels_.begin(), ms_levels_.end());
00406 
00407 
00408 
00409 
00410       if (this->chromatograms_.empty())
00411       {
00412         return;
00413       }
00414 
00415       //TODO CHROM update intensity, m/z and RT according to chromatograms as well! (done????)
00416 
00417       for (typename std::vector<ChromatogramType>::iterator it = chromatograms_.begin(); it != chromatograms_.end(); ++it)
00418       {
00419 
00420         // ignore TICs and ECs (as these are usually positioned at 0 and therefor lead to a large white margin in plots if included)
00421         if (it->getChromatogramType() == ChromatogramSettings::TOTAL_ION_CURRENT_CHROMATOGRAM ||
00422             it->getChromatogramType() == ChromatogramSettings::EMISSION_CHROMATOGRAM)
00423         {
00424           continue;
00425         }
00426 
00427         // update MZ
00428         if (it->getMZ() < RangeManagerType::pos_range_.minY()) RangeManagerType::pos_range_.setMinY(it->getMZ());
00429         if (it->getMZ() > RangeManagerType::pos_range_.maxY()) RangeManagerType::pos_range_.setMaxY(it->getMZ());
00430 
00431         // do not update RT and in if the specturm is empty
00432         if (it->size() == 0) continue;
00433 
00434         total_size_ += it->size();
00435 
00436         it->updateRanges();
00437 
00438         // RT
00439         if (it->getMin()[0] < RangeManagerType::pos_range_.minX()) RangeManagerType::pos_range_.setMinX(it->getMin()[0]);
00440         if (it->getMax()[0] > RangeManagerType::pos_range_.maxX()) RangeManagerType::pos_range_.setMaxX(it->getMax()[0]);
00441 
00442         // int
00443         if (it->getMinInt() < RangeManagerType::int_range_.minX()) RangeManagerType::int_range_.setMinX(it->getMinInt());
00444         if (it->getMaxInt() > RangeManagerType::int_range_.maxX()) RangeManagerType::int_range_.setMaxX(it->getMaxInt());
00445       }
00446     }
00447 
00449     CoordinateType getMinMZ() const
00450     {
00451       return RangeManagerType::pos_range_.minPosition()[1];
00452     }
00453 
00455     CoordinateType getMaxMZ() const
00456     {
00457       return RangeManagerType::pos_range_.maxPosition()[1];
00458     }
00459 
00461     CoordinateType getMinRT() const
00462     {
00463       return RangeManagerType::pos_range_.minPosition()[0];
00464     }
00465 
00467     CoordinateType getMaxRT() const
00468     {
00469       return RangeManagerType::pos_range_.maxPosition()[0];
00470     }
00471 
00477     const AreaType & getDataRange() const
00478     {
00479       return RangeManagerType::pos_range_;
00480     }
00481 
00483     UInt64 getSize() const
00484     {
00485       return total_size_;
00486     }
00487 
00489     const std::vector<UInt> & getMSLevels() const
00490     {
00491       return ms_levels_;
00492     }
00493 
00495 
00498 
00503     void sortSpectra(bool sort_mz = true)
00504     {
00505       std::sort(this->begin(), this->end(), typename SpectrumType::RTLess());
00506 
00507       if (sort_mz)
00508       {
00509         // sort each spectrum by m/z
00510         for (Iterator iter = this->begin(); iter != this->end(); ++iter)
00511         {
00512           iter->sortByPosition();
00513         }
00514       }
00515     }
00516 
00522     void sortChromatograms(bool sort_rt = true)
00523     {
00524       // sort the chromatograms according to their product m/z
00525       std::sort(chromatograms_.begin(), chromatograms_.end(), typename ChromatogramType::MZLess());
00526 
00527       if (sort_rt)
00528       {
00529         for (typename std::vector<ChromatogramType>::iterator it = chromatograms_.begin(); it != chromatograms_.end(); ++it)
00530         {
00531           it->sortByPosition();
00532         }
00533       }
00534     }
00535 
00541     bool isSorted(bool check_mz = true) const
00542     {
00543       //check RT positions
00544       for (Size i = 1; i < this->size(); ++i)
00545       {
00546         if (this->operator[](i - 1).getRT() > this->operator[](i).getRT()) return false;
00547       }
00548       //check spectra
00549       if (check_mz)
00550       {
00551         for (Size i = 0; i < this->size(); ++i)
00552         {
00553           if (!this->operator[](i).isSorted()) return false;
00554         }
00555       }
00556       // TODO CHROM
00557       return true;
00558     }
00559 
00561 
00563     void reset()
00564     {
00565       Base::clear();           //remove data
00566       RangeManagerType::clearRanges();           //reset range manager
00567       ExperimentalSettings::operator=(ExperimentalSettings());           //reset meta info
00568     }
00569 
00575     bool clearMetaDataArrays()
00576     {
00577       bool meta_present = false;
00578       for (Size i = 0; i < this->size(); ++i)
00579       {
00580         if (this->operator[](i).getFloatDataArrays().size() != 0 || this->operator[](i).getIntegerDataArrays().size() != 0 || this->operator[](i).getStringDataArrays().size() != 0)
00581         {
00582           meta_present = true;
00583         }
00584         this->operator[](i).getStringDataArrays().clear();
00585         this->operator[](i).getIntegerDataArrays().clear();
00586         this->operator[](i).getFloatDataArrays().clear();
00587       }
00588       return meta_present;
00589     }
00590 
00592     const ExperimentalSettings & getExperimentalSettings() const
00593     {
00594       return *this;
00595     }
00596 
00598     ExperimentalSettings & getExperimentalSettings()
00599     {
00600       return *this;
00601     }
00602 
00608     ConstIterator getPrecursorSpectrum(ConstIterator iterator) const
00609     {
00610       if (iterator == this->end() || iterator == this->begin())
00611       {
00612         return this->end();
00613       }
00614       UInt ms_level = iterator->getMSLevel();
00615       do
00616       {
00617         --iterator;
00618         if (iterator->getMSLevel() < ms_level)
00619         {
00620           return iterator;
00621         }
00622       }
00623       while (iterator != this->begin());
00624 
00625       return this->end();
00626     }
00627 
00629     void swap(MSExperiment & from)
00630     {
00631       MSExperiment tmp;
00632 
00633       //swap range information
00634       tmp.RangeManagerType::operator=(* this);
00635       this->RangeManagerType::operator=(from);
00636       from.RangeManagerType::operator=(tmp);
00637 
00638       //swap experimental settings
00639       tmp.ExperimentalSettings::operator=(* this);
00640       this->ExperimentalSettings::operator=(from);
00641       from.ExperimentalSettings::operator=(tmp);
00642 
00643       //swap persistent object
00644       tmp.PersistentObject::operator=(* this);
00645       this->PersistentObject::operator=(from);
00646       from.PersistentObject::operator=(tmp);
00647 
00648       // swap chromatograms
00649       std::swap(chromatograms_, from.chromatograms_);
00650 
00651       //swap peaks
00652       Base::swap(from);
00653 
00654       //swap remaining members
00655       ms_levels_.swap(from.ms_levels_);
00656       std::swap(total_size_, from.total_size_);
00657     }
00658 
00660     void setChromatograms(const std::vector<MSChromatogram<ChromatogramPeakType> > & chromatograms)
00661     {
00662       chromatograms_ = chromatograms;
00663     }
00664 
00666     void addChromatogram(const MSChromatogram<ChromatogramPeakType> & chromatogram)
00667     {
00668       chromatograms_.push_back(chromatogram);
00669     }
00670 
00672     const std::vector<MSChromatogram<ChromatogramPeakType> > & getChromatograms() const
00673     {
00674       return chromatograms_;
00675     }
00676 
00678     const MSChromatogram<ChromatogramPeakType> getTIC() const
00679     {
00680       // The TIC is (re)calculated from the MS1 spectra. Even if MSExperiment does not contain a TIC chromatogram explicitly, it can be reported.
00681       MSChromatogram<ChromatogramPeakType> TIC;
00682       for (typename Base::const_iterator spec_it = this->begin(); spec_it != this->end(); ++spec_it)
00683       {
00684         if (spec_it->getMSLevel() == 1)
00685         {
00686           DoubleReal totalIntensity = 0;
00687           // sum intensities of a spectrum
00688           for (typename SpectrumType::const_iterator peak_it = spec_it->begin(); peak_it != spec_it->end(); ++peak_it)
00689           {
00690             totalIntensity += peak_it->getIntensity();
00691           }
00692           // fill chromatogram
00693           ChromatogramPeakType peak;
00694           peak.setRT(spec_it->getRT());
00695           peak.setIntensity(totalIntensity);
00696           TIC.push_back(peak);
00697         }
00698       }
00699       return TIC;
00700     }
00701 
00707     void clear(bool clear_meta_data)
00708     {
00709       Base::clear();
00710 
00711       if (clear_meta_data)
00712       {
00713         clearRanges();
00714         clearId();
00715         this->ExperimentalSettings::operator=(ExperimentalSettings());             // no "clear" method
00716         chromatograms_.clear();
00717         ms_levels_.clear();
00718         total_size_ = 0;
00719       }
00720     }
00721 
00722 protected:
00723 
00724     // Docu in base class
00725     virtual void clearChildIds_()
00726     {
00727       for (Size i = 0; i < this->size(); ++i)
00728       {
00729         this->operator[](i).clearId(true);
00730       }
00731     }
00732 
00734     std::vector<UInt> ms_levels_;
00736     UInt64 total_size_;
00737 
00739     std::vector<MSChromatogram<ChromatogramPeakType> > chromatograms_;
00740   };
00741 
00743   template <typename PeakT, typename ChromatogramPeakT>
00744   std::ostream & operator<<(std::ostream & os, const MSExperiment<PeakT, ChromatogramPeakT> & exp)
00745   {
00746     os << "-- MSEXPERIMENT BEGIN --" << std::endl;
00747 
00748     //experimental settings
00749     os << static_cast<const ExperimentalSettings &>(exp);
00750 
00751     //spectra
00752     for (typename MSExperiment<PeakT>::const_iterator it = exp.begin(); it != exp.end(); ++it)
00753     {
00754       os << *it;
00755     }
00756 
00757     //chromatograms
00758     for (typename std::vector<MSChromatogram<ChromatogramPeakT> >::const_iterator it = exp.getChromatograms().begin(); it != exp.getChromatograms().end(); ++it)
00759     {
00760       os << *it;
00761     }
00762 
00763     os << "-- MSEXPERIMENT END --" << std::endl;
00764 
00765     return os;
00766   }
00767 
00768 } // namespace OpenMS
00769 
00770 #endif // OPENMS_KERNEL_MSEXPERIMENT_H

OpenMS / TOPP release 1.10.0 Documentation generated on Thu Mar 7 2013 09:42:42 using doxygen 1.7.1