CMS 3D CMS Logo

DetSetVector.h
Go to the documentation of this file.
1 #ifndef DataFormats_Common_DetSetVector_h
2 #define DataFormats_Common_DetSetVector_h
3 
4 /*----------------------------------------------------------------------
5 
6 DetSetVector: A collection of homogeneous objects that can be used for
7 an EDProduct. DetSetVector is *not* designed for use as a base class
8 (it has no virtual functions).
9 
10 DetSetVector<T> contains a vector<DetSet<T> >, sorted on DetId, and
11 provides fast (O(log n)) lookups, but only O(n) insertion.
12 
13 It provides an interface such that EdmRef2 can directly reference, and
14 provide access to, individual T objects.
15 
16 The collection appears to the user as if it were a sequence of
17 DetSet<T>; e.g., operator[] returns a DetSet<T>&. However, the
18 argument to operator[] specifies the (DetId) identifier of the vector
19 to be returned, *not* the ordinal number of the T to be returned.
20 
21  ------------------
22  It is critical that users DO NOT MODIFY the id data member of a
23  DetSet object in a DetSetVector.
24  ------------------
25 
26 Since CMSSW 2_0_0_pre4, it is possible to skip the automatic sorting
27 when creating a DetSetVector<T> from an already sorted vector<DetSet<T>>.
28 If the DSV is not modified afterwards, it will no longer be sorted when
29 it is inserted in the event.
30 ONE NOTE OF CAUTION: it is not sufficient to to say that the vector is
31 sorted already. In addition the sorting must have been done with the same
32 criteria and obey the rules of "strict weak ordering" as will be used to
33 find things in the collection. Not insuring this leads to undefined
34 behavior (usually a core dump).
35 
36 ----------------------------------------------------------------------*/
37 
38 #include <algorithm>
39 #include <iterator>
40 #include <vector>
41 
42 #include <type_traits>
43 #include "boost/concept_check.hpp"
44 
50 
52 
54 
55 namespace edm {
56  class ProductID;
57 
58  //------------------------------------------------------------
59  // Forward declarations
60  template <class T> class DetSetVector;
61 
62  //------------------------------------------------------------
63  // Helper function, to regularize throwing of exceptions.
64  //------------------------------------------------------------
65 
66  namespace detail {
67  // Throw an edm::Exception with an appropriate message
68  inline
71  "DetSetVector::operator[] called with index not in collection;\nindex value: ", i);
72  }
73  }
74 
75  //------------------------------------------------------------
76  //
77 
78  // If DetSetVector<T> is instantiated with a class T which inherits
79  // from DoNotSortUponInsertion, the resulting class inherits from
80  // DoNotSortUponInsertion. In the normal case, DetSetVector<T>
81  // inherits from Other. (This is necessary to assure that
82  // DetSetVector<T> is not sorted upon insertion into the Event when
83  // T is defined to inherit from DoNotSortUponInsertion).
84 
85  template <class T>
86  class DetSetVector :
87  public std::conditional_t<std::is_base_of<edm::DoNotSortUponInsertion, T>::value,
88  edm::DoNotSortUponInsertion,
89  Other>
90  {
93  BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
94  public:
95 
96  typedef DetSet<T> detset;
97  typedef detset value_type;
98  typedef std::vector<detset> collection_type;
99 
100  typedef detset& reference;
101  typedef detset const& const_reference;
102 
103  typedef typename collection_type::iterator iterator;
104  typedef typename collection_type::const_iterator const_iterator;
106 
109 
111  DetSetVector();
112 
124  explicit DetSetVector(std::vector<DetSet<T> > & input, bool alreadySorted=false);
125 
126 
127  void swap(DetSetVector& other);
128 
129  DetSetVector& operator= (DetSetVector const& other);
130 
132  // What should happen if there is already a DetSet with this
133  // DetId? Right now, it is up to the user *not* to do this. If you
134  // are unsure whether or not your DetId is already in the
135  // DetSetVector, then use 'find_or_insert(id)' instead.
136  void insert(detset const& s);
137 
141  reference find_or_insert(det_id_type id);
142 
144  bool empty() const;
145 
147  size_type size() const;
148 
149  // reserve...
150  void reserve(size_t s) { _sets.reserve(s);}
151 
152  // Do we need a short-hand method to return the number of T
153  // instances? If so, do we optimize for size (calculate on the
154  // fly) or speed (keep a current cache)?
155 
158  iterator find(det_id_type id);
159  const_iterator find(det_id_type id) const;
160 
164  reference operator[](det_id_type i);
165  const_reference operator[](det_id_type i) const;
166 
168  iterator begin();
169  const_iterator begin() const;
170 
172  iterator end();
173  const_iterator end() const;
174 
177  void getIds(std::vector<det_id_type> & result) const;
178 
181  void post_insert();
182 
183  void fillView(ProductID const& id,
184  std::vector<void const*>& pointers,
186 
187  //Used by ROOT storage
189 
190  private:
191  collection_type _sets;
192  edm::BoolCache _alreadySorted;
193 
195  void _sort();
196 
197  };
198 
199  template <class T>
200  inline
202  _sets()
203  { }
204 
205  template <class T>
206  inline
207  DetSetVector<T>::DetSetVector(std::vector<DetSet<T> > & input, bool alreadySorted) :
208  _sets(), _alreadySorted(alreadySorted)
209  {
210  _sets.swap(input);
211  if (!alreadySorted) _sort();
212  }
213 
214  template <class T>
215  inline
216  void
218  _sets.swap(other._sets);
220  }
221 
222  template <class T>
223  inline
226  {
227  DetSetVector<T> temp(other);
228  swap(temp);
229  return *this;
230  }
231 
232  template <class T>
233  inline
234  void
235  DetSetVector<T>::insert(detset const& t) {
236  _alreadySorted = false; // we don't know if the DetSet we're adding is already sorted
237  // Implementation provided by the Performance Task Force.
238  _sets.insert(std::lower_bound(_sets.begin(),
239  _sets.end(),
240  t),
241  t);
242 #if 0
243  // It seems we have to sort on each insertion, because we may
244  // perform lookups during construction.
245  _sets.push_back(t);
246 
247  _sort();
248 #endif
249  }
250 
251  template <class T>
252  inline
255  // NOTE: we don't have to clear _alreadySorted: the new DS is empty,
256  // and gets inserted in the correct place
257  std::pair<iterator,iterator> p =
258  std::equal_range(_sets.begin(), _sets.end(), id);
259 
260  // If the range isn't empty, we already have the right thing;
261  // return a reference to it...
262  if (p.first != p.second) return *p.first;
263 
264  // Insert the right thing, in the right place, and return a
265  // reference to the newly inserted thing.
266 #if defined( __GXX_EXPERIMENTAL_CXX0X__)
267  return *(_sets.emplace(p.first, id));
268 #else
269  return *(_sets.insert(p.first, detset(id)));
270 #endif
271  }
272 
273  template <class T>
274  inline
275  bool
277  return _sets.empty();
278  }
279 
280  template <class T>
281  inline
284  return _sets.size();
285  }
286 
287  template <class T>
288  inline
291  _alreadySorted = false; // it's non const
292  std::pair<iterator,iterator> p =
293  std::equal_range(_sets.begin(), _sets.end(), id);
294  if (p.first == p.second) return _sets.end();
295 
296  // The range indicated by [p.first, p.second) should be exactly of
297  // length 1. It seems likely we don't want to take the time hit of
298  // checking this, but here is the appropriate test... We can turn
299  // it on if we need the debugging aid.
300  #if 0
301  assert(std::distance(p.first, p.second) == 1);
302  #endif
303 
304  return p.first;
305  }
306 
307  template <class T>
308  inline
311  std::pair<const_iterator,const_iterator> p =
312  std::equal_range(_sets.begin(), _sets.end(), id);
313  if (p.first == p.second) return _sets.end();
314  // The range indicated by [p.first, p.second) should be exactly of
315  // length 1.
316  assert(std::distance(p.first, p.second) == 1);
317  return p.first;
318  }
319 
320  template <class T>
321  inline
324  _alreadySorted = false; // it's non const
325  // Find the right DetSet, and return a reference to it. Throw if
326  // there is none.
327  iterator it = this->find(i);
328  if (it == this->end()) detail::_throw_range(i);
329  return *it;
330  }
331 
332  template <class T>
333  inline
336  // Find the right DetSet, and return a reference to it. Throw if
337  // there is none.
338  const_iterator it = this->find(i);
339  if (it == this->end()) detail::_throw_range(i);
340  return *it;
341  }
342 
343  template <class T>
344  inline
347  _alreadySorted = false; // it's non const
348  return _sets.begin();
349  }
350 
351  template <class T>
352  inline
355  return _sets.begin();
356  }
357 
358  template <class T>
359  inline
362  _alreadySorted = false; // it's non const
363  return _sets.end();
364  }
365 
366  template <class T>
367  inline
370  return _sets.end();
371  }
372 
373 
374  template <class T>
375  inline
376  void
377  DetSetVector<T>::getIds(std::vector<det_id_type> & result) const
378  {
379  std::transform(this->begin(), this->end(),
380  std::back_inserter(result),
381  std::bind(&DetSet<T>::id,std::placeholders::_1));
382  }
383 
384  template <class T>
385  inline
386  void
388  _sets.shrink_to_fit();
389  if (_alreadySorted) return;
390  typename collection_type::iterator i = _sets.begin();
391  typename collection_type::iterator e = _sets.end();
392  // For each DetSet...
393  for (; i != e; ++i) {
394  i->data.shrink_to_fit();
395  // sort the Detset pointed to by
396  std::sort(i->data.begin(), i->data.end());
397  }
398  }
399 
400  template <class T>
401  inline
402  void
404  std::sort(_sets.begin(), _sets.end());
405  }
406 
407  template<class T>
409  std::vector<void const*>& pointers,
410  FillViewHelperVector& helpers) const
411  {
412  detail::reallyFillView(*this, id, pointers, helpers);
413  }
414 
415  //----------------------------------------------------------------------
416  //
417  // Free function template to support creation of Views.
418 
419  template <class T>
420  inline
421  void
423  ProductID const& id,
424  std::vector<void const*>& pointers,
425  FillViewHelperVector& helpers)
426  {
427  obj.fillView(id, pointers, helpers);
428  }
429 
430  template <class T>
432  {
433  static bool const value = true;
434  };
435 
436 
437  // Free swap function
438  template <class T>
439  inline
440  void
442  {
443  a.swap(b);
444  }
445 
446 }
447 
448 
449 //specialize behavior of edm::Ref to get access to the 'Det'
450 namespace edm {
451 
452  namespace refhelper {
453  template<typename T>
454  class FindForDetSetVector : public std::binary_function<const DetSetVector<T>&, std::pair<det_id_type, typename DetSet<T>::collection_type::size_type>, const T*> {
455  public:
457  typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) {
458  return &(*(iContainer.find(iIndex.first)->data.begin()+iIndex.second));
459  }
460  };
461 
462  template<typename T>
465  };
466  }
467 
468  //helper function to make it easier to create a edm::Ref
469 
470  template<class HandleT>
471  inline
473  makeRefTo(const HandleT& iHandle,
474  det_id_type iDetID,
475  typename HandleT::element_type::value_type::const_iterator itIter) {
476  typedef typename HandleT::element_type Vec;
478  typename Vec::const_iterator itFound = iHandle->find(iDetID);
479  if(itFound == iHandle->end()) {
481  "an edm::Ref to an edm::DetSetVector was given a DetId, ", iDetID, ", that is not in the DetSetVector");
482  }
483  index += (itIter- itFound->data.begin());
484  if(index >= itFound->data.size()) {
486  "an edm::Ref to a edm::DetSetVector is being made with an interator that is not part of the edm::DetSet itself");
487  }
488  return Ref<typename HandleT::element_type,
490  (iHandle,std::make_pair(iDetID,index));
491  }
492 
493  template<class HandleT>
494  inline
496  makeRefToDetSetVector(const HandleT& iHandle,
497  det_id_type iDetID,
498  typename HandleT::element_type::value_type::iterator itIter) {
499  typedef typename HandleT::element_type Vec;
500  typename Vec::detset::const_iterator itIter2 = itIter;
501  return makeRefTo(iHandle,iDetID,itIter2);
502  }
503 }
504 #endif
size
Write out results.
collection_type _sets
Definition: DetSetVector.h:191
void _throw_range(det_id_type i)
Definition: DetSetVector.h:69
detset const & const_reference
Definition: DetSetVector.h:101
iterator find(det_id_type id)
Definition: DetSetVector.h:290
Definition: CLHEP.h:16
DetSetVector & operator=(DetSetVector const &other)
void reserve(size_t s)
Definition: DetSetVector.h:150
void reallyFillView(COLLECTION const &coll, ProductID const &id, std::vector< void const * > &ptrs, FillViewHelperVector &helpers)
Definition: FillView.h:27
#define CMS_CLASS_VERSION(_version_)
Definition: classes.h:31
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:20
uint16_t size_type
Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type > makeRefToDetSetVector(const HandleT &iHandle, det_id_type iDetID, typename HandleT::element_type::value_type::iterator itIter)
Definition: DetSetVector.h:496
void swap(DetSetVector &other)
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:116
static std::string const input
Definition: EdmProvDump.cc:44
reference find_or_insert(det_id_type id)
Definition: DetSetVector.h:254
static void throwThis(Code category, char const *message0="", char const *message1="", char const *message2="", char const *message3="", char const *message4="")
Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type > makeRefTo(const HandleT &iHandle, det_id_type iDetID, typename HandleT::element_type::value_type::const_iterator itIter)
Definition: DetSetVector.h:473
void fillView(AssociationVector< KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper > const &obj, ProductID const &id, std::vector< void const * > &pointers, FillViewHelperVector &helpers)
T operator[](int i) const
def template(fileName, svg, replaceme="REPLACEME")
Definition: svgfig.py:520
#define end
Definition: vmac.h:37
Definition: value.py:1
bool insert(Storage &iStorage, ItemType *iItem, const IdTag &iIdTag)
Definition: HCMethods.h:49
std::vector< detset > collection_type
Definition: DetSetVector.h:98
collection_type::iterator iterator
Definition: DetSetVector.h:103
iterator end()
Return the off-the-end iterator.
Definition: DetSetVector.h:361
size_type size() const
Return the number of contained DetSets.
Definition: DetSetVector.h:283
DetSetVector()
Create an empty DetSetVector.
Definition: DetSetVector.h:201
edm::BoolCache _alreadySorted
Definition: DetSetVector.h:192
uint32_t det_id_type
Definition: DetSet.h:21
DetSet< T > detset
Definition: DetSetVector.h:96
bool empty() const
Return true if we contain no DetSets.
Definition: DetSetVector.h:276
void getIds(std::vector< det_id_type > &result) const
Definition: DetSetVector.h:377
void _sort()
Sort the DetSet in order of increasing DetId.
Definition: DetSetVector.h:403
double b
Definition: hdecay.h:120
void fillView(ProductID const &id, std::vector< void const * > &pointers, FillViewHelperVector &helpers) const
Definition: DetSetVector.h:408
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
void insert(detset const &s)
Insert the given DetSet.
Definition: DetSetVector.h:235
reference operator[](det_id_type i)
Definition: DetSetVector.h:323
#define begin
Definition: vmac.h:30
HLT enums.
collection_type::size_type size_type
Definition: DetSetVector.h:105
double a
Definition: hdecay.h:121
iterator begin()
Return an iterator to the first DetSet.
Definition: DetSetVector.h:346
self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex)
Definition: DetSetVector.h:457
collection_type::const_iterator const_iterator
Definition: DetSetVector.h:104
long double T
std::vector< std::pair< edm::ProductID, unsigned long > > FillViewHelperVector