CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 "boost/concept_check.hpp"
43 #include "boost/mpl/if.hpp"
44 #if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__REFLEX__)
45 #else
46 #include "boost/bind.hpp"
47 #endif
48 
54 
56 
58 
59 namespace edm {
60  class ProductID;
61 
62  //------------------------------------------------------------
63  // Forward declarations
64  template <class T> class DetSetVector;
65 
66  //------------------------------------------------------------
67  // Helper function, to regularize throwing of exceptions.
68  //------------------------------------------------------------
69 
70  namespace detail {
71  // Throw an edm::Exception with an appropriate message
72  inline
75  "DetSetVector::operator[] called with index not in collection;\nindex value: ", i);
76  }
77  }
78 
79  //------------------------------------------------------------
80  //
81 
82  // If DetSetVector<T> is instantiated with a class T which inherits
83  // from DoNotSortUponInsertion, the resulting class inherits from
84  // DoNotSortUponInsertion. In the normal case, DetSetVector<T>
85  // inherits from Other. (This is necessary to assure that
86  // DetSetVector<T> is not sorted upon insertion into the Event when
87  // T is defined to inherit from DoNotSortUponInsertion).
88 
89  template <class T>
90  class DetSetVector :
91  public boost::mpl::if_c<boost::is_base_of<edm::DoNotSortUponInsertion, T>::value,
92  edm::DoNotSortUponInsertion,
93  Other>::type
94  {
97  BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
98  public:
99 
100  typedef DetSet<T> detset;
102  typedef std::vector<detset> collection_type;
103 
104  typedef detset& reference;
105  typedef detset const& const_reference;
106 
107  typedef typename collection_type::iterator iterator;
108  typedef typename collection_type::const_iterator const_iterator;
110 
113 
115  DetSetVector();
116 
128  explicit DetSetVector(std::vector<DetSet<T> > & input, bool alreadySorted=false);
129 
130 
131  void swap(DetSetVector& other);
132 
133  DetSetVector& operator= (DetSetVector const& other);
134 
136  // What should happen if there is already a DetSet with this
137  // DetId? Right now, it is up to the user *not* to do this. If you
138  // are unsure whether or not your DetId is already in the
139  // DetSetVector, then use 'find_or_insert(id)' instead.
140  void insert(detset const& s);
141 
146 
148  bool empty() const;
149 
151  size_type size() const;
152 
153  // reserve...
154  void reserve(size_t s) { _sets.reserve(s);}
155 
156  // Do we need a short-hand method to return the number of T
157  // instances? If so, do we optimize for size (calculate on the
158  // fly) or speed (keep a current cache)?
159 
163  const_iterator find(det_id_type id) const;
164 
170 
172  iterator begin();
173  const_iterator begin() const;
174 
176  iterator end();
177  const_iterator end() const;
178 
181  void getIds(std::vector<det_id_type> & result) const;
182 
185  void post_insert();
186 
187  void fillView(ProductID const& id,
188  std::vector<void const*>& pointers,
189  helper_vector& helpers) const;
190 
191  //Used by ROOT storage
193 
194  private:
197 
199  void _sort();
200 
201  };
202 
203  template <class T>
204  inline
206  _sets()
207  { }
208 
209  template <class T>
210  inline
211  DetSetVector<T>::DetSetVector(std::vector<DetSet<T> > & input, bool alreadySorted) :
212  _sets(), _alreadySorted(alreadySorted)
213  {
214  _sets.swap(input);
215  if (!alreadySorted) _sort();
216  }
217 
218  template <class T>
219  inline
220  void
222  _sets.swap(other._sets);
223  bool tmp = _alreadySorted; _alreadySorted = other._alreadySorted; other._alreadySorted = tmp;
224  }
225 
226  template <class T>
227  inline
228  DetSetVector<T>&
230  {
231  DetSetVector<T> temp(other);
232  swap(temp);
233  return *this;
234  }
235 
236  template <class T>
237  inline
238  void
240  _alreadySorted = false; // we don't know if the DetSet we're adding is already sorted
241  // Implementation provided by the Performance Task Force.
242  _sets.insert(std::lower_bound(_sets.begin(),
243  _sets.end(),
244  t),
245  t);
246 #if 0
247  // It seems we have to sort on each insertion, because we may
248  // perform lookups during construction.
249  _sets.push_back(t);
250 
251  _sort();
252 #endif
253  }
254 
255  template <class T>
256  inline
259  // NOTE: we don't have to clear _alreadySorted: the new DS is empty,
260  // and gets inserted in the correct place
261  std::pair<iterator,iterator> p =
262  std::equal_range(_sets.begin(), _sets.end(), id);
263 
264  // If the range isn't empty, we already have the right thing;
265  // return a reference to it...
266  if (p.first != p.second) return *p.first;
267 
268  // Insert the right thing, in the right place, and return a
269  // reference to the newly inserted thing.
270 #if defined( __GXX_EXPERIMENTAL_CXX0X__)
271  return *(_sets.emplace(p.first, id));
272 #else
273  return *(_sets.insert(p.first, detset(id)));
274 #endif
275  }
276 
277  template <class T>
278  inline
279  bool
281  return _sets.empty();
282  }
283 
284  template <class T>
285  inline
288  return _sets.size();
289  }
290 
291  template <class T>
292  inline
295  _alreadySorted = false; // it's non const
296  std::pair<iterator,iterator> p =
297  std::equal_range(_sets.begin(), _sets.end(), id);
298  if (p.first == p.second) return _sets.end();
299 
300  // The range indicated by [p.first, p.second) should be exactly of
301  // length 1. It seems likely we don't want to take the time hit of
302  // checking this, but here is the appropriate test... We can turn
303  // it on if we need the debugging aid.
304  #if 0
305  assert(std::distance(p.first, p.second) == 1);
306  #endif
307 
308  return p.first;
309  }
310 
311  template <class T>
312  inline
315  std::pair<const_iterator,const_iterator> p =
316  std::equal_range(_sets.begin(), _sets.end(), id);
317  if (p.first == p.second) return _sets.end();
318  // The range indicated by [p.first, p.second) should be exactly of
319  // length 1.
320  assert(std::distance(p.first, p.second) == 1);
321  return p.first;
322  }
323 
324  template <class T>
325  inline
328  _alreadySorted = false; // it's non const
329  // Find the right DetSet, and return a reference to it. Throw if
330  // there is none.
331  iterator it = this->find(i);
332  if (it == this->end()) detail::_throw_range(i);
333  return *it;
334  }
335 
336  template <class T>
337  inline
340  // Find the right DetSet, and return a reference to it. Throw if
341  // there is none.
342  const_iterator it = this->find(i);
343  if (it == this->end()) detail::_throw_range(i);
344  return *it;
345  }
346 
347  template <class T>
348  inline
351  _alreadySorted = false; // it's non const
352  return _sets.begin();
353  }
354 
355  template <class T>
356  inline
359  return _sets.begin();
360  }
361 
362  template <class T>
363  inline
366  _alreadySorted = false; // it's non const
367  return _sets.end();
368  }
369 
370  template <class T>
371  inline
374  return _sets.end();
375  }
376 
377 
378  template <class T>
379  inline
380  void
381  DetSetVector<T>::getIds(std::vector<det_id_type> & result) const
382  {
383  std::transform(this->begin(), this->end(),
384  std::back_inserter(result),
385 #if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__REFLEX__)
386  std::bind(&DetSet<T>::id,std::placeholders::_1));
387 #else
388  boost::bind(&DetSet<T>::id,_1));
389 #endif
390  }
391 
392  template <class T>
393  inline
394  void
396 #ifndef CMS_NOCXX11
397  _sets.shrink_to_fit();
398 #endif
399  if (_alreadySorted) return;
400  typename collection_type::iterator i = _sets.begin();
401  typename collection_type::iterator e = _sets.end();
402  // For each DetSet...
403  for (; i != e; ++i) {
404 #ifndef CMS_NOCXX11
405  i->data.shrink_to_fit();
406 #endif
407  // sort the Detset pointed to by
408  std::sort(i->data.begin(), i->data.end());
409  }
410  }
411 
412  template <class T>
413  inline
414  void
416  std::sort(_sets.begin(), _sets.end());
417  }
418 
419  template<class T>
421  std::vector<void const*>& pointers,
422  helper_vector& helpers) const
423  {
424  detail::reallyFillView(*this, id, pointers, helpers);
425  }
426 
427  //----------------------------------------------------------------------
428  //
429  // Free function template to support creation of Views.
430 
431  template <class T>
432  inline
433  void
435  ProductID const& id,
436  std::vector<void const*>& pointers,
437  helper_vector& helpers)
438  {
439  obj.fillView(id, pointers, helpers);
440  }
441 
442  template <class T>
443  struct has_fillView<edm::DetSetVector<T> >
444  {
445  static bool const value = true;
446  };
447 
448 
449  // Free swap function
450  template <class T>
451  inline
452  void
454  {
455  a.swap(b);
456  }
457 
458 }
459 
460 
461 //specialize behavior of edm::Ref to get access to the 'Det'
462 namespace edm {
463 
464  namespace refhelper {
465  template<typename T>
466  class FindForDetSetVector : public std::binary_function<const DetSetVector<T>&, std::pair<det_id_type, typename DetSet<T>::collection_type::size_type>, const T*> {
467  public:
469  typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) {
470  return &(*(iContainer.find(iIndex.first)->data.begin()+iIndex.second));
471  }
472  };
473 
474  template<typename T>
477  };
478  }
479 
480  //helper function to make it easier to create a edm::Ref
481 
482  template<class HandleT>
484  makeRefTo(const HandleT& iHandle,
485  det_id_type iDetID,
486  typename HandleT::element_type::value_type::const_iterator itIter) {
487  typedef typename HandleT::element_type Vec;
489  typename Vec::const_iterator itFound = iHandle->find(iDetID);
490  if(itFound == iHandle->end()) {
492  "an edm::Ref to an edm::DetSetVector was given a DetId, ", iDetID, ", that is not in the DetSetVector");
493  }
494  index += (itIter- itFound->data.begin());
495  if(index >= itFound->data.size()) {
497  "an edm::Ref to a edm::DetSetVector is being made with an interator that is not part of the edm::DetSet itself");
498  }
499  return Ref<typename HandleT::element_type,
501  (iHandle,std::make_pair(iDetID,index));
502  }
503 
504  template<class HandleT>
505  Ref<typename HandleT::element_type, typename HandleT::element_type::value_type::value_type>
506  makeRefToDetSetVector(const HandleT& iHandle,
507  det_id_type iDetID,
508  typename HandleT::element_type::value_type::iterator itIter) {
509  typedef typename HandleT::element_type Vec;
510  typename Vec::detset::const_iterator itIter2 = itIter;
511  return makeRefTo(iHandle,iDetID,itIter2);
512  }
513 }
514 #endif
type
Definition: HCALResponse.h:21
collection_type _sets
Definition: DetSetVector.h:195
int i
Definition: DBlmapReader.cc:9
void _throw_range(det_id_type i)
Definition: DetSetVector.h:73
detset const & const_reference
Definition: DetSetVector.h:105
iterator find(det_id_type id)
Definition: DetSetVector.h:294
void fillView(AssociationVector< KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper > const &obj, ProductID const &id, std::vector< void const * > &pointers, helper_vector &helpers)
void reserve(size_t s)
Definition: DetSetVector.h:154
assert(m_qm.get())
void reallyFillView(COLLECTION const &coll, ProductID const &id, std::vector< void const * > &ptrs, helper_vector &helpers)
Definition: FillView.h:49
#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:7
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:506
void swap(DetSetVector &other)
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:116
static std::string const input
Definition: EdmProvDump.cc:43
reference find_or_insert(det_id_type id)
Definition: DetSetVector.h:258
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:484
tuple result
Definition: query.py:137
#define end
Definition: vmac.h:37
Container::value_type value_type
std::vector< detset > collection_type
Definition: DetSetVector.h:102
collection_type::iterator iterator
Definition: DetSetVector.h:107
iterator end()
Return the off-the-end iterator.
Definition: DetSetVector.h:365
size_type size() const
Return the number of contained DetSets.
Definition: DetSetVector.h:287
DetSetVector()
Create an empty DetSetVector.
Definition: DetSetVector.h:205
edm::BoolCache _alreadySorted
Definition: DetSetVector.h:196
uint32_t det_id_type
Definition: DetSet.h:21
DetSet< T > detset
Definition: DetSetVector.h:100
bool empty() const
Return true if we contain no DetSets.
Definition: DetSetVector.h:280
void getIds(std::vector< det_id_type > &result) const
Definition: DetSetVector.h:381
void _sort()
Sort the DetSet in order of increasing DetId.
Definition: DetSetVector.h:415
double b
Definition: hdecay.h:120
BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept)
#define private
Definition: FWFileEntry.h:17
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
void insert(detset const &s)
Insert the given DetSet.
Definition: DetSetVector.h:239
reference operator[](det_id_type i)
Definition: DetSetVector.h:327
#define begin
Definition: vmac.h:30
collection_type::size_type size_type
Definition: DetSetVector.h:109
double a
Definition: hdecay.h:121
iterator begin()
Return an iterator to the first DetSet.
Definition: DetSetVector.h:350
self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex)
Definition: DetSetVector.h:469
collection_type::const_iterator const_iterator
Definition: DetSetVector.h:108
long double T
static bool const value
Definition: traits.h:124
def template
Definition: svgfig.py:520
void fillView(ProductID const &id, std::vector< void const * > &pointers, helper_vector &helpers) const
Definition: DetSetVector.h:420
DetSetVector & operator=(DetSetVector const &other)
Definition: DetSetVector.h:229