Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4THitsMap.hh
Go to the documentation of this file.
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#include <type_traits>
37
38// class description:
39//
40// This is a template class of hits map and parametrized by
41// The concrete class of G4VHit. This is a uniform collection for
42// a particular concrete hit class objects.
43// An intermediate layer class G4HitsMap appeared in this
44// header file is used just for G4Allocator, because G4Allocator
45// cannot be instansiated with a template class. Thus G4HitsMap
46// class MUST NOT be directly used by the user.
47
48template <typename T, typename Map_t = std::map<G4int, T*>>
50{
51 private:
52 using mmap_t = std::multimap<G4int, T *>;
53 using pair_t = std::pair<G4int, T *>;
54 using uommap_t = std::unordered_multimap<G4int, T *>;
55
56#define is_same_t(_Tp, _Up) std::is_same<_Tp, _Up>::value
57#define is_multimap_t(_Mp) std::is_same<_Mp, mmap_t>::value
58#define is_uommap_t(_Mp) std::is_same<_Mp, uommap_t>::value
59#define is_mmap_t(_Mp) (is_multimap_t(_Mp) || is_uommap_t(_Mp))
60#define is_fundamental_t(_Tp) std::is_fundamental<_Tp>::value
61
62 template <bool _Bp, typename _Tp = void>
63 using enable_if_t = typename std::enable_if<_Bp, _Tp>::type;
64
65 // ensure fundamental types are initialized to zero
66 template <typename U = T, enable_if_t<is_fundamental_t(U), G4int> = 0>
67 T* allocate() const
68 {
69 return new T(0.);
70 }
71 // non-fundamental types should set values to appropriate values
72 // and avoid issues such as:
73 // G4StatDouble stat(0.); stat += 1.0; gives n == 2;
74 template <typename U = T, enable_if_t<! is_fundamental_t(U), G4int> = 0>
75 T* allocate() const
76 {
77 return new T();
78 }
79
80 public:
82 using value_type = T;
83 using map_type = Map_t;
84 using iterator = typename map_type::iterator;
85 using const_iterator = typename map_type::const_iterator;
86
87 public: // with description
88 // generic constructor
90 // det + collection description constructor
91 G4VTHitsMap(G4String detName, G4String colNam);
92 // destructor
93 ~G4VTHitsMap() override;
94 // equivalence operator
96
97 //------------------------------------------------------------------------//
98 // Generic operator += where add(...) overloads handle various
99 // U and MapU_t types
100 //------------------------------------------------------------------------//
101 template <typename U, typename MapU_t>
103 {
104 MapU_t* aHitsMap = right.GetMap();
105 for (auto itr = aHitsMap->begin(); itr != aHitsMap->end(); ++itr)
106 add<U, map_type>(itr->first, *(itr->second));
107 return (this_type&)(*this);
108 }
109 //------------------------------------------------------------------------//
110
111 public: // with description
112 void DrawAllHits() override;
113 void PrintAllHits() override;
114 // These two methods invokes Draw() and Print() methods of all of
115 // hit objects stored in this map, respectively.
116
117 public:
118 // Generic iteration
119 inline Map_t* GetContainer() const { return (Map_t*)theCollection; }
120
121 inline typename Map_t::size_type size() { return GetContainer()->size(); }
122
123 inline typename Map_t::size_type GetIndex(iterator itr) { return itr->first; }
124
125 inline typename Map_t::size_type GetIndex(const_iterator itr) const { return itr->first; }
126
127 template <typename MapU_t = Map_t, enable_if_t<! is_mmap_t(MapU_t), G4int> = 0>
128 inline T* GetObject(G4int idx) const
129 {
130 return (GetContainer()->count(idx) != 0) ? (*GetContainer())[idx] : nullptr;
131 }
132
133 template <typename MapU_t = Map_t, enable_if_t<is_mmap_t(MapU_t), G4int> = 0>
134 inline T* GetObject(G4int idx) const
135 {
136 return (GetContainer()->count(idx) != 0) ? GetContainer()->find(idx)->second : nullptr;
137 }
138
139 inline T* GetObject(iterator itr) const { return itr->second; }
140
141 inline const T* GetObject(const_iterator itr) const { return itr->second; }
142
143 iterator begin() { return GetContainer()->begin(); }
144 iterator end() { return GetContainer()->end(); }
145 const_iterator begin() const { return GetContainer()->begin(); }
146 const_iterator end() const { return GetContainer()->end(); }
147 const_iterator cbegin() const { return GetContainer()->cbegin(); }
148 const_iterator cend() const { return GetContainer()->cend(); }
149
150 public: // with description
151 // Returns a pointer to a concrete hit object.
152 inline Map_t* GetMap() const { 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 { return ((Map_t*)theCollection)->size(); }
156 // Returns the number of hit objects stored in this map
157 inline void clear();
158
159 public:
160 G4VHit* GetHit(size_t) const override { return nullptr; }
161 size_t GetSize() const override { return ((Map_t*)theCollection)->size(); }
162
163 public:
164 //------------------------------------------------------------------------//
165 // Add/Insert a hit object. Total number of hit objects stored in this
166 // map is returned.
167 //------------------------------------------------------------------------//
168 // Standard map overload for same type
169 //------------------------------------------------------------------------//
170 // here we don't use allocate() since instances like G4Colour() == white
171 // and += adds to white (not correct)
172 template <typename U = T, typename MapU_t = Map_t,
173 enable_if_t<is_same_t(U, T) && ! is_mmap_t(MapU_t), G4int> = 0>
174 size_t add(const G4int& key, U*& aHit) const
175 {
176 map_type* theHitsMap = GetMap();
177 if (theHitsMap->find(key) == theHitsMap->end())
178 theHitsMap->insert(pair_t(key, new T(*aHit)));
179 else
180 *theHitsMap->find(key)->second += *aHit;
181 return theHitsMap->size();
182 }
183 //------------------------------------------------------------------------//
184 // Multimap overload for same type T
185 //------------------------------------------------------------------------//
186 template <typename U = T, typename MapU_t = Map_t,
187 enable_if_t<(is_same_t(U, T) && is_mmap_t(MapU_t)), G4int> = 0>
188 size_t add(const G4int& key, U*& aHit) const
189 {
190 map_type* theHitsMap = GetMap();
191 theHitsMap->insert(pair_t(key, aHit));
192 return theHitsMap->size();
193 }
194 //------------------------------------------------------------------------//
195 // Multimap overload for different types
196 // assumes type T has overload of += operator for U
197 //------------------------------------------------------------------------//
198 template <typename U = T, typename MapU_t = Map_t,
199 enable_if_t<(! is_same_t(U, T) && is_mmap_t(MapU_t)), G4int> = 0>
200 size_t add(const G4int& key, U*& aHit) const
201 {
202 map_type* theHitsMap = GetMap();
203 T* hit = allocate();
204 *hit += *aHit;
205 theHitsMap->insert(pair_t(key, hit));
206 return theHitsMap->size();
207 }
208
209 public:
210 //------------------------------------------------------------------------//
211 // Standard map overload for same type
212 // assumes type T has overload of += operator for U
213 //------------------------------------------------------------------------//
214 // here we don't use allocate() since instances like G4Colour() == white
215 // and += adds to white (not correct)
216 template <typename U = T, typename MapU_t = Map_t,
217 enable_if_t<(is_same_t(U, T) && ! is_mmap_t(MapU_t)), G4int> = 0>
218 size_t add(const G4int& key, U& aHit) const
219 {
220 map_type* theHitsMap = GetMap();
221 if (theHitsMap->find(key) == theHitsMap->end())
222 theHitsMap->insert(pair_t(key, new T(aHit)));
223 else
224 *theHitsMap->find(key)->second += aHit;
225 return theHitsMap->size();
226 }
227 //------------------------------------------------------------------------//
228 // Standard map overload for different type
229 // assumes type T has overload of += operator for U
230 //------------------------------------------------------------------------//
231 template <typename U = T, typename MapU_t = Map_t,
232 enable_if_t<(! is_same_t(U, T) && ! is_mmap_t(MapU_t)), G4int> = 0>
233 size_t add(const G4int& key, U& aHit) const
234 {
235 map_type* theHitsMap = GetMap();
236 if (theHitsMap->find(key) == theHitsMap->end()) theHitsMap->insert(pair_t(key, allocate()));
237 *theHitsMap->find(key)->second += aHit;
238 return theHitsMap->size();
239 }
240 //------------------------------------------------------------------------//
241 // Multimap overload for same type T
242 //------------------------------------------------------------------------//
243 template <typename U = T, typename MapU_t = Map_t,
244 enable_if_t<(is_same_t(U, T) && is_mmap_t(MapU_t)), G4int> = 0>
245 size_t add(const G4int& key, U& aHit) const
246 {
247 map_type* theHitsMap = GetMap();
248 theHitsMap->insert(pair_t(key, new T(aHit)));
249 return theHitsMap->size();
250 }
251 //------------------------------------------------------------------------//
252 // Multimap overload for different types
253 // assumes type T has overload of += operator for U
254 //------------------------------------------------------------------------//
255 template <typename U = T, typename MapU_t = Map_t,
256 enable_if_t<(! is_same_t(U, T) && is_mmap_t(MapU_t)), G4int> = 0>
257 size_t add(const G4int& key, U& aHit) const
258 {
259 map_type* theHitsMap = GetMap();
260 T* hit = allocate();
261 *hit += aHit;
262 theHitsMap->insert(pair_t(key, hit));
263 return theHitsMap->size();
264 }
265 //------------------------------------------------------------------------//
266
267 public:
268 //------------------------------------------------------------------------//
269 // Set a hit object. Total number of hit objects stored in this
270 // map is returned.
271 //------------------------------------------------------------------------//
272 // Standard overload for same type T
273 //------------------------------------------------------------------------//
274 template <typename U = T, typename MapU_t = Map_t,
275 enable_if_t<(is_same_t(U, T) && ! is_mmap_t(MapU_t)), G4int> = 0>
276 inline size_t set(const G4int& key, U*& aHit) const
277 {
278 map_type* theHitsMap = GetMap();
279 if (theHitsMap->find(key) != theHitsMap->end()) delete theHitsMap->find(key)->second;
280 theHitsMap->find(key)->second = aHit;
281 return theHitsMap->size();
282 }
283 //------------------------------------------------------------------------//
284 // Multimap overload for same type T
285 //------------------------------------------------------------------------//
286 template <typename U = T, typename MapU_t = Map_t,
287 enable_if_t<(is_same_t(U, T) && is_mmap_t(MapU_t)), G4int> = 0>
288 inline size_t set(const G4int& key, U*& aHit) const
289 {
290 map_type* theHitsMap = GetMap();
291 if (theHitsMap->find(key) != theHitsMap->end())
292 theHitsMap->insert(pair_t(key, aHit));
293 else {
294 delete theHitsMap->find(key)->second;
295 theHitsMap->find(key)->second = aHit;
296 }
297 return theHitsMap->size();
298 }
299 //------------------------------------------------------------------------//
300 // Standard map overload for different types
301 //------------------------------------------------------------------------//
302 template <typename U = T, typename MapU_t = Map_t,
303 enable_if_t<(! is_same_t(U, T) && ! is_mmap_t(MapU_t)), G4int> = 0>
304 inline size_t set(const G4int& key, U*& aHit) const
305 {
306 map_type* theHitsMap = GetMap();
307 T* hit = nullptr;
308 if (theHitsMap->find(key) == theHitsMap->end())
309 theHitsMap->insert(std::make_pair(key, hit = allocate()));
310 else
311 hit = theHitsMap->find(key)->second;
312 *hit += *aHit;
313 return theHitsMap->size();
314 }
315 //------------------------------------------------------------------------//
316 // Multimap overload for different types
317 //------------------------------------------------------------------------//
318 template <typename U = T, typename MapU_t = Map_t,
319 enable_if_t<(! is_same_t(U, T) && is_mmap_t(MapU_t)), G4int> = 0>
320 inline size_t set(const G4int& key, U*& aHit) const
321 {
322 map_type* theHitsMap = GetMap();
323 T* hit = allocate();
324 *hit += *aHit;
325 if (theHitsMap->find(key) != theHitsMap->end())
326 theHitsMap->insert(pair_t(key, hit));
327 else {
328 delete theHitsMap->find(key)->second;
329 theHitsMap->find(key)->second = hit;
330 }
331 return theHitsMap->size();
332 }
333 //------------------------------------------------------------------------//
334
335 public:
336 //------------------------------------------------------------------------//
337 // Set a hit object. Total number of hit objects stored in this
338 // map is returned.
339 //------------------------------------------------------------------------//
340 // Standard overload for same type T
341 //------------------------------------------------------------------------//
342 template <typename U = T, typename MapU_t = Map_t,
343 enable_if_t<(is_same_t(U, T) && ! is_mmap_t(MapU_t)), G4int> = 0>
344 inline size_t set(const G4int& key, U& aHit) const
345 {
346 map_type* theHitsMap = GetMap();
347 T* hit = nullptr;
348 if (theHitsMap->find(key) != theHitsMap->end())
349 hit = theHitsMap->find(key)->second;
350 else
351 theHitsMap->insert(pair_t(key, hit = allocate()));
352 *hit = aHit;
353 return theHitsMap->size();
354 }
355 //------------------------------------------------------------------------//
356 // Multimap overload for same type T
357 //------------------------------------------------------------------------//
358 template <typename U = T, typename MapU_t = Map_t,
359 enable_if_t<(is_same_t(U, T) && is_mmap_t(MapU_t)), G4int> = 0>
360 inline size_t set(const G4int& key, U& aHit) const
361 {
362 map_type* theHitsMap = GetMap();
363 if (theHitsMap->find(key) != theHitsMap->end())
364 *theHitsMap->find(key)->second = aHit;
365 else
366 theHitsMap->insert(pair_t(key, new T(aHit)));
367 return theHitsMap->size();
368 }
369 //------------------------------------------------------------------------//
370 // Standard map overload for different types
371 //------------------------------------------------------------------------//
372 template <typename U = T, typename MapU_t = Map_t,
373 enable_if_t<(! is_same_t(U, T) && ! is_mmap_t(MapU_t)), G4int> = 0>
374 inline size_t set(const G4int& key, U& aHit) const
375 {
376 map_type* theHitsMap = GetMap();
377 T* hit = nullptr;
378 if (theHitsMap->find(key) == theHitsMap->end())
379 theHitsMap->insert(std::make_pair(key, hit = allocate()));
380 else
381 hit = theHitsMap->find(key)->second;
382 *hit += aHit;
383 return theHitsMap->size();
384 }
385 //------------------------------------------------------------------------//
386 // Multimap overload for different types
387 //------------------------------------------------------------------------//
388 template <typename U = T, typename MapU_t = Map_t,
389 enable_if_t<(! is_same_t(U, T) && is_mmap_t(MapU_t)), G4int> = 0>
390 inline size_t set(const G4int& key, U& aHit) const
391 {
392 map_type* theHitsMap = GetMap();
393 T* hit = allocate();
394 *hit += aHit;
395 if (theHitsMap->find(key) != theHitsMap->end())
396 *theHitsMap->find(key)->second = *hit;
397 else
398 theHitsMap->insert(pair_t(key, hit));
399 return theHitsMap->size();
400 }
401 //------------------------------------------------------------------------//
402
403 public:
404 //------------------------------------------------------------------------//
405 // Enable bracket operator. Return pointer to data indexed by key or
406 // last occurring instance of pointer to data index by key in the
407 // case of a multimap
408 //------------------------------------------------------------------------//
409 template <typename MapU_t = Map_t, enable_if_t<! is_mmap_t(MapU_t), G4int> = 0>
410 T* operator[](G4int key) const
411 {
412 map_type* theHitsMap = GetMap();
413 if (theHitsMap->find(key) != theHitsMap->end()) return theHitsMap->find(key)->second;
414 return nullptr;
415 }
416 //------------------------------------------------------------------------//
417 template <typename MapU_t = Map_t, enable_if_t<is_mmap_t(MapU_t), G4int> = 0>
418 T* operator[](G4int key) const
419 {
420#ifdef G4VERBOSE
421 static bool _first = true;
422 if (_first) {
423 _first = false;
424 G4Exception("G4THitsMap operator[]", "calling [] on multimap", JustWarning,
425 "Returning the last matching entry");
426 }
427#endif
428 map_type* theHitsMap = GetMap();
429 iterator itr = theHitsMap->find(key);
430 if (itr != theHitsMap->end()) {
431 std::advance(itr, theHitsMap->count(key) - 1);
432 return itr->second;
433 }
434 return nullptr;
435 }
436 //------------------------------------------------------------------------//
437
438#undef is_same_t
439#undef is_multimap_t
440#undef is_uommap_t
441#undef is_mmap_t
442#undef is_fundamental_t
443};
444
445//============================================================================//
446
447template <typename T, typename Map_t>
449{
450 theCollection = (void*)new Map_t;
451}
452
453//============================================================================//
454
455template <typename T, typename Map_t>
457 : G4HitsCollection(detName, colNam)
458{
459 theCollection = (void*)new Map_t;
460}
461
462//============================================================================//
463
464template <typename T, typename Map_t>
466{
467 map_type* theHitsMap = GetMap();
468 for (auto itr = theHitsMap->begin(); itr != theHitsMap->end(); ++itr)
469 delete itr->second;
470 delete theHitsMap;
471}
472
473//============================================================================//
474
475template <typename T, typename Map_t>
477{
478 return (collectionName == right.collectionName);
479}
480
481//============================================================================//
482
483template <typename T, typename Map_t>
488
489//============================================================================//
490
491template <typename T, typename Map_t>
493{
494 G4cout << "G4THitsMap " << SDname << " / " << collectionName << " --- " << entries() << " entries"
495 << G4endl;
496 /*----- commented out for the use-case where <T> cannot be initialized
497 to be zero or does not support += operator.
498 Map_t * theHitsMap = GetMap();
499 typename Map_t::iterator itr = theHitsMap->begin();
500 T sum = 0.;
501 for(; itr != theHitsMap->end(); ++itr) {
502 G4cout << " " << itr->first << " : "
503 << *(itr->second) << G4endl;
504 sum += *(itr->second);
505 }
506 G4cout << " Total : " << sum << G4endl;
507 ----------------------------------------------------------------------*/
508}
509
510//============================================================================//
511
512template <typename T, typename Map_t>
514{
515 Map_t* theHitsMap = GetMap();
516 for (iterator itr = theHitsMap->begin(); itr != theHitsMap->end(); ++itr)
517 delete itr->second;
518 theHitsMap->clear();
519}
520
521//============================================================================//
522// //
523// //
524// Helpers for different map types //
525// //
526// //
527//============================================================================//
528
529template <typename _Tp>
531{
532 public:
534
535 public:
537 G4THitsMap(G4String detName, G4String colName) : parent_type(detName, colName) {}
538
539 using parent_type::operator+=;
540 using parent_type::operator==;
541 using parent_type::operator[];
542 using parent_type::add;
543 using parent_type::begin;
544 using parent_type::cbegin;
545 using parent_type::cend;
546 using parent_type::clear;
547 using parent_type::DrawAllHits;
548 using parent_type::end;
549 using parent_type::entries;
550 using parent_type::GetHit;
551 using parent_type::GetMap;
552 using parent_type::GetSize;
553 using parent_type::PrintAllHits;
554 using parent_type::set;
555};
556
557//============================================================================//
558
559template <typename _Tp>
560class G4THitsMultiMap : public G4VTHitsMap<_Tp, std::multimap<G4int, _Tp*>>
561{
562 public:
564
565 public:
567 G4THitsMultiMap(G4String detName, G4String colName) : parent_type(detName, colName) {}
568
569 using parent_type::operator+=;
570 using parent_type::operator==;
571 using parent_type::operator[];
572 using parent_type::add;
573 using parent_type::begin;
575 using parent_type::cend;
576 using parent_type::clear;
578 using parent_type::end;
584 using parent_type::set;
585};
586
587//============================================================================//
588
589template <typename _Tp>
590class G4THitsUnorderedMap : public G4VTHitsMap<_Tp, std::unordered_map<G4int, _Tp*>>
591{
592 public:
594
595 public:
597 G4THitsUnorderedMap(G4String detName, G4String colName) : parent_type(detName, colName) {}
598
599 using parent_type::operator+=;
600 using parent_type::operator==;
601 using parent_type::operator[];
602 using parent_type::add;
603 using parent_type::begin;
605 using parent_type::cend;
606 using parent_type::clear;
608 using parent_type::end;
614 using parent_type::set;
615};
616
617//============================================================================//
618
619template <typename _Tp>
620class G4THitsUnorderedMultiMap : public G4VTHitsMap<_Tp, std::unordered_multimap<G4int, _Tp*>>
621{
622 public:
624
625 public:
627 G4THitsUnorderedMultiMap(G4String detName, G4String colName) : parent_type(detName, colName) {}
628
629 using parent_type::operator+=;
630 using parent_type::operator==;
631 using parent_type::operator[];
632 using parent_type::add;
633 using parent_type::begin;
635 using parent_type::cend;
636 using parent_type::clear;
638 using parent_type::end;
644 using parent_type::set;
645};
646
647//============================================================================//
648
649#endif
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define is_mmap_t(_Mp)
Definition G4THitsMap.hh:59
#define is_same_t(_Tp, _Up)
Definition G4THitsMap.hh:56
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
G4THitsMap(G4String detName, G4String colName)
G4THitsMultiMap(G4String detName, G4String colName)
G4THitsUnorderedMap(G4String detName, G4String colName)
G4THitsUnorderedMultiMap(G4String detName, G4String colName)
Map_t * GetMap() const
G4VHit * GetHit(size_t) const override
const_iterator cbegin() const
this_type & operator+=(const G4VTHitsMap< U, MapU_t > &right) const
typename map_type::iterator iterator
Definition G4THitsMap.hh:84
const T * GetObject(const_iterator itr) const
size_t set(const G4int &key, U *&aHit) const
~G4VTHitsMap() override
G4bool operator==(const G4VTHitsMap< T, Map_t > &right) const
size_t set(const G4int &key, U &aHit) const
Map_t * GetContainer() const
Map_t::size_type GetIndex(iterator itr)
const_iterator end() const
size_t entries() const
void DrawAllHits() override
iterator end()
G4VTHitsMap(G4String detName, G4String colNam)
Map_t::size_type size()
const_iterator begin() const
T * operator[](G4int key) const
const_iterator cend() const
Map_t map_type
Definition G4THitsMap.hh:83
void PrintAllHits() override
T * GetObject(iterator itr) const
size_t GetSize() const override
Map_t::size_type GetIndex(const_iterator itr) const
size_t add(const G4int &key, U &aHit) const
typename map_type::const_iterator const_iterator
Definition G4THitsMap.hh:85
iterator begin()
size_t add(const G4int &key, U *&aHit) const
T * GetObject(G4int idx) const