ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4THitsMap.hh
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4THitsMap.hh
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 //
28 #ifndef G4THitsMap_h
29 #define G4THitsMap_h 1
30 
31 #include "G4THitsCollection.hh"
32 #include "globals.hh"
33 
34 #include <map>
35 #include <unordered_map>
36 
37 // class description:
38 //
39 // This is a template class of hits map and parametrized by
40 // The concrete class of G4VHit. This is a uniform collection for
41 // a particular concrete hit class objects.
42 // An intermediate layer class G4HitsMap appeared in this
43 // header file is used just for G4Allocator, because G4Allocator
44 // cannot be instansiated with a template class. Thus G4HitsMap
45 // class MUST NOT be directly used by the user.
46 
47 template <typename T, typename Map_t = std::map<G4int, T*> >
49 {
50 private:
51  typedef std::multimap<G4int, T*> mmap_t;
52  typedef std::pair<G4int, T*> pair_t;
53  typedef std::unordered_multimap<G4int, T*> uommap_t;
54 
55  #define is_same_t(_Tp, _Up) std::is_same<_Tp, _Up>::value
56  #define is_multimap_t(_Mp) std::is_same<_Mp, mmap_t>::value
57  #define is_uommap_t(_Mp) std::is_same<_Mp, uommap_t>::value
58  #define is_mmap_t(_Mp) (is_multimap_t(_Mp) || is_uommap_t(_Mp))
59  #define is_fundamental_t(_Tp) std::is_fundamental<_Tp>::value
60 
61  template <bool _Bp, typename _Tp = void>
62  using enable_if_t = typename std::enable_if<_Bp, _Tp>::type;
63 
64  // ensure fundamental types are initialized to zero
65  template <typename U = T, enable_if_t<is_fundamental_t(U), int> = 0>
66  T* allocate() const
67  { return new T(0.); }
68  // non-fundamental types should set values to appropriate values
69  // and avoid issues such as:
70  // G4StatDouble stat(0.); stat += 1.0; gives n == 2;
71  template <typename U = T, enable_if_t<! is_fundamental_t(U), int> = 0>
72  T* allocate() const
73  { return new T(); }
74 
75 public:
77  typedef T value_type;
78  typedef Map_t map_type;
79  typedef typename map_type::iterator iterator;
80  typedef typename map_type::const_iterator const_iterator;
81 
82 public: // with description
83  // generic constructor
84  G4VTHitsMap();
85  // det + collection description constructor
86  G4VTHitsMap(G4String detName, G4String colNam);
87  // destructor
88  virtual ~G4VTHitsMap();
89  // equivalence operator
91 
92  //------------------------------------------------------------------------//
93  // Generic operator += where add(...) overloads handle various
94  // U and MapU_t types
95  //------------------------------------------------------------------------//
96  template <typename U, typename MapU_t>
98  {
99  MapU_t* aHitsMap = right.GetMap();
100  for(auto itr = aHitsMap->begin(); itr != aHitsMap->end(); ++itr)
101  add<U, map_type>(itr->first, *(itr->second));
102  return (this_type&)(*this);
103  }
104  //------------------------------------------------------------------------//
105 
106 public: // with description
107  virtual void DrawAllHits();
108  virtual void PrintAllHits();
109  // These two methods invokes Draw() and Print() methods of all of
110  // hit objects stored in this map, respectively.
111 
112 public:
113  // Generic iteration
114  inline Map_t* GetContainer() const
115  { return (Map_t*) theCollection; }
116 
117  inline typename Map_t::size_type size()
118  { return GetContainer()->size(); }
119 
120  inline typename Map_t::size_type GetIndex(iterator itr)
121  { return itr->first; }
122 
123  inline typename Map_t::size_type GetIndex(const_iterator itr) const
124  { return itr->first; }
125 
126  template <typename MapU_t = Map_t, enable_if_t< !is_mmap_t(MapU_t), int> = 0>
127  inline T* GetObject(G4int idx) const
128  { return (GetContainer()->count(idx) != 0) ? (*GetContainer())[idx] : nullptr; }
129 
130  template <typename MapU_t = Map_t, enable_if_t< is_mmap_t(MapU_t), int> = 0>
131  inline T* GetObject(G4int idx) const
132  {
133  return (GetContainer()->count(idx) != 0) ? GetContainer()->find(idx)->second : nullptr;
134  }
135 
136  inline T* GetObject(iterator itr) const
137  { return itr->second; }
138 
139  inline const T* GetObject(const_iterator itr) const
140  { return itr->second; }
141 
142  iterator begin() { return GetContainer()->begin(); }
143  iterator end() { return GetContainer()->end(); }
144  const_iterator begin() const { return GetContainer()->begin(); }
145  const_iterator end() const { return GetContainer()->end(); }
146  const_iterator cbegin() const { return GetContainer()->cbegin(); }
147  const_iterator cend() const { return GetContainer()->cend(); }
148 
149 public: // with description
150  // Returns a pointer to a concrete hit object.
151  inline Map_t* GetMap() const
152  { return (Map_t*)theCollection; }
153  // Overwrite a hit object. Total number of hit objects stored in this
154  // map is returned.
155  inline size_t entries() const
156  { return ((Map_t*)theCollection)->size(); }
157  // Returns the number of hit objects stored in this map
158  inline void clear();
159 
160 public:
161  virtual G4VHit* GetHit(size_t) const {return 0;}
162  virtual size_t GetSize() const
163  { return ((Map_t*)theCollection)->size(); }
164 
165 public:
166  //------------------------------------------------------------------------//
167  // Add/Insert a hit object. Total number of hit objects stored in this
168  // map is returned.
169  //------------------------------------------------------------------------//
170  // Standard map overload for same type
171  //------------------------------------------------------------------------//
172  // here we don't use allocate() since instances like G4Colour() == white
173  // and += adds to white (not correct)
174  template <typename U = T,
175  typename MapU_t = Map_t,
176  enable_if_t<is_same_t(U, T) && ! is_mmap_t(MapU_t), int> = 0>
177  size_t add(const G4int& key, U*& aHit) const
178  {
179  map_type* theHitsMap = GetMap();
180  if(theHitsMap->find(key) == theHitsMap->end())
181  theHitsMap->insert(pair_t(key, new T(*aHit)));
182  else
183  *theHitsMap->find(key)->second += *aHit;
184  return theHitsMap->size();
185  }
186  //------------------------------------------------------------------------//
187  // Multimap overload for same type T
188  //------------------------------------------------------------------------//
189  template <typename U = T,
190  typename MapU_t = Map_t,
191  enable_if_t<(is_same_t(U, T) && is_mmap_t(MapU_t)), int> = 0>
192  size_t add(const G4int& key, U*& aHit) const
193  {
194  map_type* theHitsMap = GetMap();
195  theHitsMap->insert(pair_t(key, aHit));
196  return theHitsMap->size();
197  }
198  //------------------------------------------------------------------------//
199  // Multimap overload for different types
200  // assumes type T has overload of += operator for U
201  //------------------------------------------------------------------------//
202  template <typename U = T,
203  typename MapU_t = Map_t,
204  enable_if_t<(!is_same_t(U, T) && is_mmap_t(MapU_t)), int> = 0>
205  size_t add(const G4int& key, U*& aHit) const
206  {
207  map_type* theHitsMap = GetMap();
208  T* hit = allocate();
209  *hit += *aHit;
210  theHitsMap->insert(pair_t(key, hit));
211  return theHitsMap->size();
212  }
213 
214 public:
215  //------------------------------------------------------------------------//
216  // Standard map overload for same type
217  // assumes type T has overload of += operator for U
218  //------------------------------------------------------------------------//
219  // here we don't use allocate() since instances like G4Colour() == white
220  // and += adds to white (not correct)
221  template <typename U = T,
222  typename MapU_t = Map_t,
223  enable_if_t<(is_same_t(U, T) && ! is_mmap_t(MapU_t)), int> = 0>
224  size_t add(const G4int& key, U& aHit) const
225  {
226  map_type* theHitsMap = GetMap();
227  if(theHitsMap->find(key) == theHitsMap->end())
228  theHitsMap->insert(pair_t(key, new T(aHit)));
229  else
230  *theHitsMap->find(key)->second += aHit;
231  return theHitsMap->size();
232  }
233  //------------------------------------------------------------------------//
234  // Standard map overload for different type
235  // assumes type T has overload of += operator for U
236  //------------------------------------------------------------------------//
237  template <typename U = T,
238  typename MapU_t = Map_t,
239  enable_if_t<(! is_same_t(U, T) && ! is_mmap_t(MapU_t)), int> = 0>
240  size_t add(const G4int& key, U& aHit) const
241  {
242  map_type* theHitsMap = GetMap();
243  if(theHitsMap->find(key) == theHitsMap->end())
244  theHitsMap->insert(pair_t(key, allocate()));
245  *theHitsMap->find(key)->second += aHit;
246  return theHitsMap->size();
247  }
248  //------------------------------------------------------------------------//
249  // Multimap overload for same type T
250  //------------------------------------------------------------------------//
251  template <typename U = T,
252  typename MapU_t = Map_t,
253  enable_if_t<(is_same_t(U, T) && is_mmap_t(MapU_t)), int> = 0>
254  size_t add(const G4int& key, U& aHit) const
255  {
256  map_type* theHitsMap = GetMap();
257  theHitsMap->insert(pair_t(key, new T(aHit)));
258  return theHitsMap->size();
259  }
260  //------------------------------------------------------------------------//
261  // Multimap overload for different types
262  // assumes type T has overload of += operator for U
263  //------------------------------------------------------------------------//
264  template <typename U = T,
265  typename MapU_t = Map_t,
266  enable_if_t<(!is_same_t(U, T) && is_mmap_t(MapU_t)), int> = 0>
267  size_t add(const G4int& key, U& aHit) const
268  {
269  map_type* theHitsMap = GetMap();
270  T* hit = allocate();
271  *hit += aHit;
272  theHitsMap->insert(pair_t(key, hit));
273  return theHitsMap->size();
274  }
275  //------------------------------------------------------------------------//
276 
277 public:
278  //------------------------------------------------------------------------//
279  // Set a hit object. Total number of hit objects stored in this
280  // map is returned.
281  //------------------------------------------------------------------------//
282  // Standard overload for same type T
283  //------------------------------------------------------------------------//
284  template <typename U = T,
285  typename MapU_t = Map_t,
286  enable_if_t<(is_same_t(U, T) && ! is_mmap_t(MapU_t)), int> = 0>
287  inline size_t set(const G4int& key, U*& aHit) const
288  {
289  map_type* theHitsMap = GetMap();
290  if(theHitsMap->find(key) != theHitsMap->end())
291  delete theHitsMap->find(key)->second;
292  theHitsMap->find(key)->second = aHit;
293  return theHitsMap->size();
294  }
295  //------------------------------------------------------------------------//
296  // Multimap overload for same type T
297  //------------------------------------------------------------------------//
298  template <typename U = T,
299  typename MapU_t = Map_t,
300  enable_if_t<(is_same_t(U, T) && is_mmap_t(MapU_t)), int> = 0>
301  inline size_t set(const G4int& key, U*& aHit) const
302  {
303  map_type* theHitsMap = GetMap();
304  if(theHitsMap->find(key) != theHitsMap->end())
305  theHitsMap->insert(pair_t(key, aHit));
306  else
307  {
308  delete theHitsMap->find(key)->second;
309  theHitsMap->find(key)->second = aHit;
310  }
311  return theHitsMap->size();
312  }
313  //------------------------------------------------------------------------//
314  // Standard map overload for different types
315  //------------------------------------------------------------------------//
316  template <typename U = T,
317  typename MapU_t = Map_t,
318  enable_if_t<(!is_same_t(U, T) && ! is_mmap_t(MapU_t)), int> = 0>
319  inline size_t set(const G4int & key, U*& aHit) const
320  {
321  map_type* theHitsMap = GetMap();
322  T* hit = nullptr;
323  if(theHitsMap->find(key) == theHitsMap->end())
324  theHitsMap->insert(std::make_pair(key, hit = allocate()));
325  else
326  hit = theHitsMap->find(key)->second;
327  *hit += *aHit;
328  return theHitsMap->size();
329  }
330  //------------------------------------------------------------------------//
331  // Multimap overload for different types
332  //------------------------------------------------------------------------//
333  template <typename U = T,
334  typename MapU_t = Map_t,
335  enable_if_t<(!is_same_t(U, T) && is_mmap_t(MapU_t)), int> = 0>
336  inline size_t set(const G4int& key, U*& aHit) const
337  {
338  map_type* theHitsMap = GetMap();
339  T* hit = allocate();
340  *hit += *aHit;
341  if(theHitsMap->find(key) != theHitsMap->end())
342  theHitsMap->insert(pair_t(key, hit));
343  else
344  {
345  delete theHitsMap->find(key)->second;
346  theHitsMap->find(key)->second = hit;
347  }
348  return theHitsMap->size();
349  }
350  //------------------------------------------------------------------------//
351 
352 public:
353  //------------------------------------------------------------------------//
354  // Set a hit object. Total number of hit objects stored in this
355  // map is returned.
356  //------------------------------------------------------------------------//
357  // Standard overload for same type T
358  //------------------------------------------------------------------------//
359  template <typename U = T,
360  typename MapU_t = Map_t,
361  enable_if_t<(is_same_t(U, T) && ! is_mmap_t(MapU_t)), int> = 0>
362  inline size_t set(const G4int& key, U& aHit) const
363  {
364  map_type* theHitsMap = GetMap();
365  T* hit = nullptr;
366  if(theHitsMap->find(key) != theHitsMap->end())
367  hit = theHitsMap->find(key)->second;
368  else
369  theHitsMap->insert(pair_t(key, hit = allocate()));
370  *hit = aHit;
371  return theHitsMap->size();
372  }
373  //------------------------------------------------------------------------//
374  // Multimap overload for same type T
375  //------------------------------------------------------------------------//
376  template <typename U = T,
377  typename MapU_t = Map_t,
378  enable_if_t<(is_same_t(U, T) && is_mmap_t(MapU_t)), int> = 0>
379  inline size_t set(const G4int& key, U& aHit) const
380  {
381  map_type* theHitsMap = GetMap();
382  if(theHitsMap->find(key) != theHitsMap->end())
383  *theHitsMap->find(key)->second = aHit;
384  else
385  theHitsMap->insert(pair_t(key, new T(aHit)));
386  return theHitsMap->size();
387  }
388  //------------------------------------------------------------------------//
389  // Standard map overload for different types
390  //------------------------------------------------------------------------//
391  template <typename U = T,
392  typename MapU_t = Map_t,
393  enable_if_t<(!is_same_t(U, T) && ! is_mmap_t(MapU_t)), int> = 0>
394  inline size_t set(const G4int & key, U& aHit) const
395  {
396  map_type* theHitsMap = GetMap();
397  T* hit = nullptr;
398  if(theHitsMap->find(key) == theHitsMap->end())
399  theHitsMap->insert(std::make_pair(key, hit = allocate()));
400  else
401  hit = theHitsMap->find(key)->second;
402  *hit += aHit;
403  return theHitsMap->size();
404  }
405  //------------------------------------------------------------------------//
406  // Multimap overload for different types
407  //------------------------------------------------------------------------//
408  template <typename U = T,
409  typename MapU_t = Map_t,
410  enable_if_t<(!is_same_t(U, T) && is_mmap_t(MapU_t)), int> = 0>
411  inline size_t set(const G4int& key, U& aHit) const
412  {
413  map_type* theHitsMap = GetMap();
414  T* hit = allocate();
415  *hit += aHit;
416  if(theHitsMap->find(key) != theHitsMap->end())
417  *theHitsMap->find(key)->second = *hit;
418  else
419  theHitsMap->insert(pair_t(key, hit));
420  return theHitsMap->size();
421  }
422  //------------------------------------------------------------------------//
423 
424 public:
425  //------------------------------------------------------------------------//
426  // Enable bracket operator. Return pointer to data indexed by key or
427  // last occurring instance of pointer to data index by key in the
428  // case of a multimap
429  //------------------------------------------------------------------------//
430  template <typename MapU_t = Map_t,
431  enable_if_t<! is_mmap_t(MapU_t), int> = 0>
432  T* operator[](G4int key) const
433  {
434  map_type* theHitsMap = GetMap();
435  if(theHitsMap->find(key) != theHitsMap->end())
436  return theHitsMap->find(key)->second;
437  return nullptr;
438  }
439  //------------------------------------------------------------------------//
440  template <typename MapU_t = Map_t,
441  enable_if_t<is_mmap_t(MapU_t), int> = 0>
442  T* operator[](G4int key) const
443  {
444 #ifdef G4VERBOSE
445  static bool _first = true;
446  if(_first)
447  {
448  _first = false;
449  G4Exception("G4THitsMap operator[]", "calling [] on multimap",
450  JustWarning, "Returning the last matching entry");
451  }
452 #endif
453  map_type* theHitsMap = GetMap();
454  iterator itr = theHitsMap->find(key);
455  if(itr != theHitsMap->end())
456  {
457  std::advance(itr, theHitsMap->count(key)-1);
458  return itr->second;
459  }
460  return nullptr;
461  }
462  //------------------------------------------------------------------------//
463 
464  #undef is_same_t
465  #undef is_multimap_t
466  #undef is_uommap_t
467  #undef is_mmap_t
468  #undef is_fundamental_t
469 };
470 
471 //============================================================================//
472 
473 template <typename T, typename Map_t>
475 {
476  theCollection = (void*)new Map_t;
477 }
478 
479 //============================================================================//
480 
481 template <typename T, typename Map_t>
483  : G4HitsCollection(detName,colNam)
484 {
485  theCollection = (void*)new Map_t;
486 }
487 
488 //============================================================================//
489 
490 template <typename T, typename Map_t>
492 {
493  map_type* theHitsMap = GetMap();
494  for(iterator itr = theHitsMap->begin(); itr != theHitsMap->end(); itr++)
495  delete itr->second;
496  delete theHitsMap;
497 }
498 
499 //============================================================================//
500 
501 template <typename T, typename Map_t>
503 {
504  return (collectionName==right.collectionName);
505 }
506 
507 //============================================================================//
508 
509 template <typename T, typename Map_t>
511 {;}
512 
513 //============================================================================//
514 
515 template <typename T, typename Map_t>
517 {
518  G4cout << "G4THitsMap " << SDname << " / " << collectionName << " --- "
519  << entries() << " entries" << G4endl;
520  /*----- commented out for the use-case where <T> cannot be initialized
521  to be zero or does not support += operator.
522  Map_t * theHitsMap = GetMap();
523  typename Map_t::iterator itr = theHitsMap->begin();
524  T sum = 0.;
525  for(; itr != theHitsMap->end(); itr++) {
526  G4cout << " " << itr->first << " : "
527  << *(itr->second) << G4endl;
528  sum += *(itr->second);
529  }
530  G4cout << " Total : " << sum << G4endl;
531  ----------------------------------------------------------------------*/
532 }
533 
534 //============================================================================//
535 
536 template <typename T, typename Map_t>
538 {
539  Map_t * theHitsMap = GetMap();
540  for(iterator itr = theHitsMap->begin(); itr != theHitsMap->end(); itr++)
541  delete itr->second;
542  theHitsMap->clear();
543 }
544 
545 //============================================================================//
546 // //
547 // //
548 // Helpers for different map types //
549 // //
550 // //
551 //============================================================================//
552 
553 template <typename _Tp>
554 class G4THitsMap : public G4VTHitsMap<_Tp, std::map<G4int, _Tp*>>
555 {
556 public:
558 
559 public:
561  G4THitsMap(G4String detName,G4String colName)
562  : parent_type(detName, colName) { }
563 
564  using parent_type::operator +=;
565  using parent_type::operator ==;
566  using parent_type::operator [];
569  using parent_type::GetMap;
570  using parent_type::entries;
571  using parent_type::clear;
572  using parent_type::begin;
573  using parent_type::end;
574  using parent_type::cbegin;
575  using parent_type::cend;
576  using parent_type::GetHit;
577  using parent_type::GetSize;
578  using parent_type::add;
579  using parent_type::set;
580 };
581 
582 //============================================================================//
583 
584 template <typename _Tp>
585 class G4THitsMultiMap : public G4VTHitsMap<_Tp, std::multimap<G4int, _Tp*>>
586 {
587 public:
589 
590 public:
593  : parent_type(detName, colName) { }
594 
595  using parent_type::operator +=;
596  using parent_type::operator ==;
597  using parent_type::operator [];
600  using parent_type::GetMap;
601  using parent_type::entries;
602  using parent_type::clear;
603  using parent_type::begin;
604  using parent_type::end;
605  using parent_type::cbegin;
606  using parent_type::cend;
607  using parent_type::GetHit;
608  using parent_type::GetSize;
609  using parent_type::add;
610  using parent_type::set;
611 };
612 
613 //============================================================================//
614 
615 template <typename _Tp>
617  : public G4VTHitsMap<_Tp, std::unordered_map<G4int, _Tp*>>
618 {
619 public:
621 
622 public:
625  : parent_type(detName, colName) { }
626 
627  using parent_type::operator +=;
628  using parent_type::operator ==;
629  using parent_type::operator [];
632  using parent_type::GetMap;
633  using parent_type::entries;
634  using parent_type::clear;
635  using parent_type::begin;
636  using parent_type::end;
637  using parent_type::cbegin;
638  using parent_type::cend;
639  using parent_type::GetHit;
640  using parent_type::GetSize;
641  using parent_type::add;
642  using parent_type::set;
643 };
644 
645 //============================================================================//
646 
647 template <typename _Tp>
649  : public G4VTHitsMap<_Tp, std::unordered_multimap<G4int, _Tp*>>
650 {
651 public:
653 
654 public:
657  : parent_type(detName, colName) { }
658 
659  using parent_type::operator +=;
660  using parent_type::operator ==;
661  using parent_type::operator [];
664  using parent_type::GetMap;
665  using parent_type::entries;
666  using parent_type::clear;
667  using parent_type::begin;
668  using parent_type::end;
669  using parent_type::cbegin;
670  using parent_type::cend;
671  using parent_type::GetHit;
672  using parent_type::GetSize;
673  using parent_type::add;
674  using parent_type::set;
675 };
676 
677 //============================================================================//
678 
679 #endif