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  // reserve...
152  void reserve(size_t s) { _sets.reserve(s);}
153 
154  // Do we need a short-hand method to return the number of T
155  // instances? If so, do we optimize for size (calculate on the
156  // fly) or speed (keep a current cache)?
157 
161  const_iterator find(det_id_type id) const;
162 
168 
170  iterator begin();
171  const_iterator begin() const;
172 
174  iterator end();
175  const_iterator end() const;
176 
179  void getIds(std::vector<det_id_type> & result) const;
180 
183  void post_insert();
184 
185  void fillView(ProductID const& id,
186  std::vector<void const*>& pointers,
187  helper_vector& helpers) const;
188 
189  //Used by ROOT storage
191 
192  private:
195 
197  void _sort();
198 
199  };
200 
201  template <class T>
202  inline
204  _sets()
205  { }
206 
207  template <class T>
208  inline
209  DetSetVector<T>::DetSetVector(std::vector<DetSet<T> > & input, bool alreadySorted) :
210  _sets(), _alreadySorted(alreadySorted)
211  {
212  _sets.swap(input);
213  if (!alreadySorted) _sort();
214  }
215 
216  template <class T>
217  inline
218  void
220  _sets.swap(other._sets);
221  bool tmp = _alreadySorted; _alreadySorted = other._alreadySorted; other._alreadySorted = tmp;
222  }
223 
224  template <class T>
225  inline
226  DetSetVector<T>&
228  {
229  DetSetVector<T> temp(other);
230  swap(temp);
231  return *this;
232  }
233 
234  template <class T>
235  inline
236  void
238  _alreadySorted = false; // we don't know if the DetSet we're adding is already sorted
239  // Implementation provided by the Performance Task Force.
240  _sets.insert(std::lower_bound(_sets.begin(),
241  _sets.end(),
242  t),
243  t);
244 #if 0
245  // It seems we have to sort on each insertion, because we may
246  // perform lookups during construction.
247  _sets.push_back(t);
248 
249  _sort();
250 #endif
251  }
252 
253  template <class T>
254  inline
257  // NOTE: we don't have to clear _alreadySorted: the new DS is empty,
258  // and gets inserted in the correct place
259  std::pair<iterator,iterator> p =
260  std::equal_range(_sets.begin(), _sets.end(), id);
261 
262  // If the range isn't empty, we already have the right thing;
263  // return a reference to it...
264  if (p.first != p.second) return *p.first;
265 
266  // Insert the right thing, in the right place, and return a
267  // reference to the newly inserted thing.
268 #if defined( __GXX_EXPERIMENTAL_CXX0X__)
269  return *(_sets.emplace(p.first, id));
270 #else
271  return *(_sets.insert(p.first, detset(id)));
272 #endif
273  }
274 
275  template <class T>
276  inline
277  bool
279  return _sets.empty();
280  }
281 
282  template <class T>
283  inline
286  return _sets.size();
287  }
288 
289  template <class T>
290  inline
293  _alreadySorted = false; // it's non const
294  std::pair<iterator,iterator> p =
295  std::equal_range(_sets.begin(), _sets.end(), id);
296  if (p.first == p.second) return _sets.end();
297 
298  // The range indicated by [p.first, p.second) should be exactly of
299  // length 1. It seems likely we don't want to take the time hit of
300  // checking this, but here is the appropriate test... We can turn
301  // it on if we need the debugging aid.
302  #if 0
303  assert(std::distance(p.first, p.second) == 1);
304  #endif
305 
306  return p.first;
307  }
308 
309  template <class T>
310  inline
313  std::pair<const_iterator,const_iterator> p =
314  std::equal_range(_sets.begin(), _sets.end(), id);
315  if (p.first == p.second) return _sets.end();
316  // The range indicated by [p.first, p.second) should be exactly of
317  // length 1.
318  assert(std::distance(p.first, p.second) == 1);
319  return p.first;
320  }
321 
322  template <class T>
323  inline
326  _alreadySorted = false; // it's non const
327  // Find the right DetSet, and return a reference to it. Throw if
328  // there is none.
329  iterator it = this->find(i);
330  if (it == this->end()) detail::_throw_range(i);
331  return *it;
332  }
333 
334  template <class T>
335  inline
338  // Find the right DetSet, and return a reference to it. Throw if
339  // there is none.
340  const_iterator it = this->find(i);
341  if (it == this->end()) detail::_throw_range(i);
342  return *it;
343  }
344 
345  template <class T>
346  inline
349  _alreadySorted = false; // it's non const
350  return _sets.begin();
351  }
352 
353  template <class T>
354  inline
357  return _sets.begin();
358  }
359 
360  template <class T>
361  inline
364  _alreadySorted = false; // it's non const
365  return _sets.end();
366  }
367 
368  template <class T>
369  inline
372  return _sets.end();
373  }
374 
375 
376  template <class T>
377  inline
378  void
379  DetSetVector<T>::getIds(std::vector<det_id_type> & result) const
380  {
381  std::transform(this->begin(), this->end(),
382  std::back_inserter(result),
383  boost::bind(&DetSet<T>::id,_1));
384  }
385 
386  template <class T>
387  inline
388  void
390  if (_alreadySorted) return;
391  typename collection_type::iterator i = _sets.begin();
392  typename collection_type::iterator e = _sets.end();
393  // For each DetSet...
394  for (; i != e; ++i) {
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  helper_vector& 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  helper_vector& helpers)
426  {
427  obj.fillView(id, pointers, helpers);
428  }
429 
430  template <class T>
431  struct has_fillView<edm::DetSetVector<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>
472  makeRefTo(const HandleT& iHandle,
473  det_id_type iDetID,
474  typename HandleT::element_type::value_type::const_iterator itIter) {
475  typedef typename HandleT::element_type Vec;
477  typename Vec::const_iterator itFound = iHandle->find(iDetID);
478  if(itFound == iHandle->end()) {
480  "an edm::Ref to an edm::DetSetVector was given a DetId, ", iDetID, ", that is not in the DetSetVector");
481  }
482  index += (itIter- itFound->data.begin());
483  if(index >= itFound->data.size()) {
485  "an edm::Ref to a edm::DetSetVector is being made with an interator that is not part of the edm::DetSet itself");
486  }
487  return Ref<typename HandleT::element_type,
489  (iHandle,std::make_pair(iDetID,index));
490  }
491 
492  template<class HandleT>
493  Ref<typename HandleT::element_type, typename HandleT::element_type::value_type::value_type>
494  makeRefToDetSetVector(const HandleT& iHandle,
495  det_id_type iDetID,
496  typename HandleT::element_type::value_type::iterator itIter) {
497  typedef typename HandleT::element_type Vec;
498  typename Vec::detset::const_iterator itIter2 = itIter;
499  return makeRefTo(iHandle,iDetID,itIter2);
500  }
501 }
502 #endif
type
Definition: HCALResponse.h:21
collection_type _sets
Definition: DetSetVector.h:193
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:292
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:152
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:494
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:256
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:472
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:100
collection_type::iterator iterator
Definition: DetSetVector.h:105
iterator end()
Return the off-the-end iterator.
Definition: DetSetVector.h:363
size_type size() const
Return the number of contained DetSets.
Definition: DetSetVector.h:285
DetSetVector()
Create an empty DetSetVector.
Definition: DetSetVector.h:203
edm::BoolCache _alreadySorted
Definition: DetSetVector.h:194
uint32_t det_id_type
Definition: DetSet.h:21
DetSet< T > detset
Definition: DetSetVector.h:98
bool empty() const
Return true if we contain no DetSets.
Definition: DetSetVector.h:278
void getIds(std::vector< det_id_type > &result) const
Definition: DetSetVector.h:379
void _sort()
Sort the DetSet in order of increasing DetId.
Definition: DetSetVector.h:403
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:237
reference operator[](det_id_type i)
Definition: DetSetVector.h:325
#define begin
Definition: vmac.h:30
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:348
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:106
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:408
DetSetVector & operator=(DetSetVector const &other)
Definition: DetSetVector.h:227