| OpenMS 2.5.0

UniqueIdIndexer.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-2020.
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: Chris Bielow $
32 // $Authors: Clemens Groepl $
33 // --------------------------------------------------------------------------
34
35 #pragma once
36
37 #include <OpenMS/CONCEPT/UniqueIdInterface.h>
38 #include <OpenMS/CONCEPT/LogStream.h>
39 #include <OpenMS/CONCEPT/Exception.h>
40
41 #ifdef _MSC_VER // disable some BOOST warnings that distract from ours
42 # pragma warning( push ) // save warning state
43 # pragma warning( disable : 4396 )
44 #endif
45
46 #include <boost/unordered_map.hpp>
47
48 #ifdef _MSC_VER
49 # pragma warning( pop ) // restore old warning state
50 #endif
51
52
53 namespace OpenMS
54 {
55
62 template <typename RandomAccessContainer>
63 class UniqueIdIndexer
64 {
65 public:
66
67 typedef boost::unordered_map<UInt64, Size> UniqueIdMap;
68
84 Size
85 uniqueIdToIndex(UInt64 unique_id) const
86 {
87 Size index;
88 try
89 {
90 index = uniqueid_to_index_.at(unique_id);
91 if (getBase_().at(index).getUniqueId() != unique_id)
92 {
93 throw std::out_of_range("unique_id_to_index_");
94 }
95 }
96 catch (std::out_of_range &)
97 {
98 try
99 {
100 this->updateUniqueIdToIndex();
101 index = uniqueid_to_index_.at(unique_id);
102 }
103 catch (std::out_of_range &)
104 {
105 index = -1; // which means: invalid
106 }
107 }
108 return index;
109 }
110
115 void
116 updateUniqueIdToIndex() const
117 {
118 Size num_valid_unique_id = 0;
119 // add or update unique id of existing features
120 for (Size index = 0; index < getBase_().size(); ++index)
121 {
122 UInt64 unique_id = getBase_()[index].getUniqueId();
123 if (UniqueIdInterface::isValid(unique_id))
124 {
125 uniqueid_to_index_[unique_id] = index;
126 ++num_valid_unique_id;
127 }
128 }
129 // remove invalid or outdated entries
130 uniqueid_to_index_.erase(UniqueIdInterface::INVALID);
131 for (UniqueIdMap::iterator iter = uniqueid_to_index_.begin(); iter != uniqueid_to_index_.end(); /* see loop */)
132 {
133 if (iter->second >= getBase_().size() || getBase_()[iter->second].getUniqueId() != iter->first)
134 {
135 iter = uniqueid_to_index_.erase(iter);
136 }
137 else
138 {
139 ++iter;
140 }
141 }
142 if (uniqueid_to_index_.size() != num_valid_unique_id)
143 {
144 std::stringstream ss;
145 ss << "Duplicate valid unique ids detected! RandomAccessContainer has size()==" << getBase_().size();
146 ss << ", num_valid_unique_id==" << num_valid_unique_id;
147 ss << ", uniqueid_to_index_.size()==" << uniqueid_to_index_.size();
148 throw Exception::Postcondition(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, ss.str());
149 }
150 return;
151 }
152
166 Size
167 resolveUniqueIdConflicts()
168 {
169 Size invalid_uids(0);
170 uniqueid_to_index_.clear();
171 // add unique id of existing features
172 for (Size index = 0; index < getBase_().size(); ++index)
173 {
174 UInt64 unique_id = getBase_()[index].getUniqueId();
175 if (!UniqueIdInterface::isValid(unique_id))
176 {
177 getBase_()[index].ensureUniqueId();
178 unique_id = getBase_()[index].getUniqueId();
179 }
180
181 // see if UID already present
182 while (uniqueid_to_index_.find(unique_id) != uniqueid_to_index_.end()) // double entry!
183 {
184 getBase_()[index].setUniqueId();
185 unique_id = getBase_()[index].getUniqueId();
186 ++invalid_uids;
187 }
188
189 uniqueid_to_index_[unique_id] = index;
190
191 }
192
193 return invalid_uids;
194 }
195
200 void
201 swap(UniqueIdIndexer & rhs)
202 {
203 std::swap(uniqueid_to_index_, rhs.uniqueid_to_index_);
204 return;
205 }
206
207 protected:
208
213 const RandomAccessContainer &
214 getBase_() const
215 {
216 return *static_cast<const RandomAccessContainer *>(this);
217 }
218
223 RandomAccessContainer &
224 getBase_()
225 {
226 return *static_cast<RandomAccessContainer *>(this);
227 }
228
233 mutable UniqueIdMap uniqueid_to_index_;
234
235 };
236
237 } //namespace OpenMS
238
OpenMS::UniqueIdIndexer::UniqueIdMap
boost::unordered_map< UInt64, Size > UniqueIdMap
Definition: UniqueIdIndexer.h:67
OpenMS::UniqueIdIndexer::resolveUniqueIdConflicts
Size resolveUniqueIdConflicts()
Assign new UID&#39;s to doubly occurring UID&#39;s.
Definition: UniqueIdIndexer.h:167
OpenMS::UniqueIdInterface::INVALID
Definition: UniqueIdInterface.h:61
OpenMS::UInt64
OPENMS_UINT64_TYPE UInt64
Unsigned integer type (64bit)
Definition: Types.h:77
OpenMS::UniqueIdInterface::isValid
static bool isValid(UInt64 unique_id)
Returns true if the unique_id is valid, false otherwise.
Definition: UniqueIdInterface.h:69
UniqueIdInterface.h
Exception.h
OpenMS::Exception::Postcondition
Postcondition failed exception.
Definition: Exception.h:180
OpenMS::UniqueIdIndexer::uniqueid_to_index_
UniqueIdMap uniqueid_to_index_
hash map from unique id to index of features
Definition: UniqueIdIndexer.h:233
OpenMS::UniqueIdIndexer::uniqueIdToIndex
Size uniqueIdToIndex(UInt64 unique_id) const
Returns the index of the feature with the given unique id, or Size(-1) if none exists in this random ...
Definition: UniqueIdIndexer.h:85
OpenMS
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:46
LogStream.h
OpenMS::UniqueIdIndexer::getBase_
RandomAccessContainer & getBase_()
A little helper to get access to the base (!) class RandomAccessContainer.
Definition: UniqueIdIndexer.h:224
OpenMS::UniqueIdIndexer
A base class for random access containers for classes derived from UniqueIdInterface that adds functi...
Definition: UniqueIdIndexer.h:63
OpenMS::UniqueIdIndexer::updateUniqueIdToIndex
void updateUniqueIdToIndex() const
Updates the hash map from unique id to index.
Definition: UniqueIdIndexer.h:116
OpenMS::UniqueIdIndexer::swap
void swap(UniqueIdIndexer &rhs)
Swap.
Definition: UniqueIdIndexer.h:201
OpenMS::UniqueIdIndexer::getBase_
const RandomAccessContainer & getBase_() const
A little helper to get access to the base (!) class RandomAccessContainer.
Definition: UniqueIdIndexer.h:214
OpenMS::Size
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition: Types.h:127