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