Project
Loading...
Searching...
No Matches
Detector.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
15#ifndef ALICEO2_BASE_DETECTOR_H_
16#define ALICEO2_BASE_DETECTOR_H_
17
18#include <map>
19#include <tbb/concurrent_unordered_map.h>
20#include <vector>
21#include <initializer_list>
22#include <memory>
23
24#include "FairDetector.h" // for FairDetector
25#include "FairRootManager.h"
27#include "Rtypes.h" // for Float_t, Int_t, Double_t, Detector::Class, etc
28#include <cxxabi.h>
29#include <typeinfo>
30#include <type_traits>
31#include <string>
34#include <sys/shm.h>
35#include <atomic>
36#include <type_traits>
37#include <unistd.h>
38#include <cassert>
39#include <list>
40#include <mutex>
41#include <thread>
42
43#include <fairmq/FwdDecls.h>
44
45namespace o2::base
46{
47
50class Detector : public FairDetector
51{
52
53 public:
54 Detector(const char* name, Bool_t Active);
55
57 Detector();
58
60 ~Detector() override;
61
62 // Module composition
63 void Material(Int_t imat, const char* name, Float_t a, Float_t z, Float_t dens, Float_t radl, Float_t absl,
64 Float_t* buf = nullptr, Int_t nwbuf = 0);
65
66 void Mixture(Int_t imat, const char* name, Float_t* a, Float_t* z, Float_t dens, Int_t nlmat,
67 Float_t* wmat);
68
69 void Medium(Int_t numed, const char* name, Int_t nmat, Int_t isvol, Int_t ifield, Float_t fieldm,
70 Float_t tmaxfd, Float_t stemax, Float_t deemax, Float_t epsil, Float_t stmin, Float_t* ubuf = nullptr,
71 Int_t nbuf = 0);
72
74 void SpecialCuts(Int_t numed, const std::initializer_list<std::pair<ECut, Float_t>>& parIDValMap);
76 void SpecialCut(Int_t numed, ECut parID, Float_t val);
77
78 void SpecialProcesses(Int_t numed, const std::initializer_list<std::pair<EProc, int>>& parIDValMap);
80 void SpecialProcess(Int_t numed, EProc parID, int val);
81
90 void Matrix(Int_t& nmat, Double_t theta1, Double_t phi1, Double_t theta2, Double_t phi2, Double_t theta3,
91 Double_t phi3) const;
92
93 static void setDensityFactor(Float_t density)
94 {
95 mDensityFactor = density;
96 }
97
99 {
100 return mDensityFactor;
101 }
102
105 void SetSpecialPhysicsCuts() override;
106
108 virtual void addAlignableVolumes() const;
109
111 virtual void fillParallelWorld() const;
112
114 virtual void defineWrapperVolume(Int_t id, Double_t rmin, Double_t rmax, Double_t zspan);
115
117 virtual void setNumberOfWrapperVolumes(Int_t n);
118
119 virtual void defineLayer(Int_t nlay, Double_t phi0, Double_t r, Int_t nladd, Int_t nmod,
120 Double_t lthick = 0., Double_t dthick = 0., UInt_t detType = 0, Int_t buildFlag = 0);
121
122 virtual void defineLayerTurbo(Int_t nlay, Double_t phi0, Double_t r, Int_t nladd, Int_t nmod,
123 Double_t width, Double_t tilt, Double_t lthick = 0., Double_t dthick = 0.,
124 UInt_t detType = 0, Int_t buildFlag = 0);
125
126 // returns global material ID given a "local" material ID for this detector
127 // returns -1 in case local ID not found
128 int getMaterialID(int imat) const
129 {
131 return mgr.getMaterialID(GetName(), imat);
132 }
133
134 // returns global medium ID given a "local" medium ID for this detector
135 // returns -1 in case local ID not found
136 int getMediumID(int imed) const
137 {
139 return mgr.getMediumID(GetName(), imed);
140 }
141
142 // fill the medium index mapping into a standard vector
143 // the vector gets sized properly and will be overridden
144 void getMediumIDMappingAsVector(std::vector<int>& mapping)
145 {
147 mgr.getMediumIDMappingAsVector(GetName(), mapping);
148 }
149
150 // return the name augmented by extension
151 std::string addNameTo(const char* ext) const
152 {
153 std::string s(GetName());
154 return s + ext;
155 }
156
157 // returning the name of the branch (corresponding to probe)
158 // returns zero length string when probe not defined
159 virtual std::string getHitBranchNames(int probe) const = 0;
160
161 // interface to update track indices of data objects
162 // usually called by the Stack, at the end of an event, which might have changed
163 // the track indices due to filtering
164 // FIXME: make private friend of stack?
165 virtual void updateHitTrackIndices(std::map<int, int> const&) = 0;
166
167 // the index a hit's track ended up at after the stack filtered the event;
168 // a pruned track has no entry in the mapping and gets the invalid index -1
169 static int updatedTrackIndex(std::map<int, int> const& indexmapping, int trackID)
170 {
171 const auto iter = indexmapping.find(trackID);
172 return iter != indexmapping.end() ? iter->second : -1;
173 }
174
175 // the index a hit or a track reference gets when the sub-events of one event
176 // are concatenated; an index already flagged invalid carries no track to
177 // shift and stays invalid
178 static int offsetTrackIndex(int trackID, int nprimaries, int primaryOffset, int secondaryOffset)
179 {
180 if (trackID < 0) {
181 return trackID;
182 }
183 return trackID + (trackID < nprimaries ? primaryOffset : secondaryOffset);
184 }
185
186 // interfaces to attach properly encoded hit information to a FairMQ message
187 // and to decode it
188 virtual void attachHits(fair::mq::Channel&, fair::mq::Parts&) = 0;
189 virtual void fillHitBranch(TTree& tr, fair::mq::Parts& parts, int& index) = 0;
190 virtual void collectHits(int eventID, fair::mq::Parts& parts, int& index, bool shm) = 0;
191 virtual void mergeHitEntriesAndFlush(int eventID,
192 TTree& target,
193 std::vector<int> const& trackoffsets,
194 std::vector<int> const& nprimaries,
195 std::vector<int> const& subevtsOrdered) = 0;
196
197 // interface needed to merge together hit entries in TBranches (as used by hit merger process)
198 // trackoffsets: a map giving the corresponding trackoffset to be applied to the trackID property when
199 // merging
200 virtual void mergeHitEntries(TTree& origin, TTree& target, std::vector<int> const& trackoffsets, std::vector<int> const& nprimaries, std::vector<int> const& subevtsOrdered) = 0;
201
202 // hook which is called automatically to custom initialize the O2 detectors
203 // all initialization not able to do in constructors should be done here
204 // (typically the case for geometry related stuff, etc)
205 virtual void InitializeO2Detector() = 0;
206
207 // the original FairModule/Detector virtual Initialize function
208 // calls individual customized initializations and makes sure that the mother Initialize
209 // is called as well. Marked final for this reason!
210 void Initialize() final
211 {
213 // make sure the basic initialization is also done
214 FairDetector::Initialize();
215 }
216
217 // a second initialization method for stuff that should be initialized late
218 // (in our case after forking off from the main simulation setup
219 // ... for things that should be setup in each simulation worker separately)
220 virtual void initializeLate() = 0;
221
224 int registerSensitiveVolumeAndGetVolID(std::string const& name);
225
228 int registerSensitiveVolumeAndGetVolID(TGeoVolume const* vol);
229
230 // The GetCollection interface is made final and deprecated since
231 // we no longer support TClonesArrays
232 [[deprecated("Use getHits API on concrete detectors!")]] TClonesArray* GetCollection(int iColl) const final;
233
234 // static and reusable service function to set tracking parameters in relation to field
235 // returns global integration mode (inhomogenety) for the field and the max field value
236 // which is required for media creation
237 static void initFieldTrackingParams(int& mode, float& maxfield);
238
240 static void setDetId2HitBitIndex(std::vector<int> const& v) { Detector::sDetId2HitBitIndex = v; }
241 static std::vector<int> const& getDetId2HitBitIndex() { return Detector::sDetId2HitBitIndex; }
242
243 protected:
244 Detector(const Detector& origin);
245
246 Detector& operator=(const Detector&);
247
248 private:
253 std::map<int, int> mMapMaterial;
254
256 std::map<int, int> mMapMedium;
257
258 static Float_t mDensityFactor;
259 // systematic studies)
260 static std::vector<int> sDetId2HitBitIndex;
261
262 ClassDefOverride(Detector, 1); // Base class for ALICE Modules
263};
264
266inline std::string demangle(const char* name)
267{
268 int status = -4; // some arbitrary value to eliminate compiler warnings
269 std::unique_ptr<char, void (*)(void*)> res{abi::__cxa_demangle(name, nullptr, nullptr, &status), std::free};
270 return (status == 0) ? res.get() : name;
271}
272
273// a flag in shared memory telling whether the hit merger still reads a hit buffer
274using ShmBusyFlag = std::atomic<bool>;
275
276void attachShmMessage(void* hitsptr, fair::mq::Channel& channel, fair::mq::Parts& parts, ShmBusyFlag* busy_ptr);
277void* decodeShmCore(fair::mq::Parts& dataparts, int index, ShmBusyFlag*& busy);
278
279template <typename T>
280T decodeShmMessage(fair::mq::Parts& dataparts, int index, ShmBusyFlag*& busy)
281{
282 return reinterpret_cast<T>(decodeShmCore(dataparts, index, busy));
283}
284
285// this goes into the source
286void attachMessageBufferToParts(fair::mq::Parts& parts, fair::mq::Channel& channel, void* data, TClass* cl);
287
288template <typename Container>
289void attachTMessage(Container const& hits, fair::mq::Channel& channel, fair::mq::Parts& parts)
290{
291 attachMessageBufferToParts(parts, channel, (void*)&hits, TClass::GetClass(typeid(hits)));
292}
293
294void* decodeTMessageCore(fair::mq::Parts& dataparts, int index);
295template <typename T>
296T decodeTMessage(fair::mq::Parts& dataparts, int index)
297{
298 return static_cast<T>(decodeTMessageCore(dataparts, index));
299}
300
301// header message preceding the hits of one detector
303 int detID;
304 bool shm; // whether the hits follow as shared-memory references or as TMessages
305};
306
307void attachHitsHeaderMessage(HitsHeader const& header, fair::mq::Channel& channel, fair::mq::Parts& parts);
308
309template <typename T>
310TBranch* getOrMakeBranch(TTree& tree, const char* brname, T* ptr)
311{
312 if (auto br = tree.GetBranch(brname)) {
313 br->SetAddress(static_cast<void*>(&ptr));
314 return br;
315 }
316 // otherwise make it
317 return tree.Branch(brname, ptr);
318}
319
320// a trait to determine if we should use shared mem or serialize using TMessage
321template <typename Det>
322struct UseShm {
323 static constexpr bool value = false;
324};
325
326// an implementation helper template which automatically implements
327// common functionality for deriving classes via the CRT pattern
328// (example: it implements the updateHitTrackIndices function and avoids
329// code duplication, while at the same time avoiding virtual function calls)
330template <typename Det>
332{
333 public:
334 // offer same constructors as base
335 using Detector::Detector;
336
337 // default implementation for getHitBranchNames
338 std::string getHitBranchNames(int probe) const override
339 {
340 if (probe == 0) {
341 return addNameTo("Hit");
342 }
343 return std::string(); // empty string as undefined
344 }
345
346 // generic implementation for the updateHitTrackIndices interface
347 // assumes Detectors have a GetHits(int) function that return some iterable
348 // hits which are o2::BaseHits
349 void updateHitTrackIndices(std::map<int, int> const& indexmapping) override
350 {
351 int probe = 0; // some Detectors have multiple hit vectors and we are probing
352 // them via a probe integer until we get a nullptr
353 while (auto hits = static_cast<Det*>(this)->Det::getHits(probe++)) {
354 for (auto& hit : *hits) {
355 hit.SetTrackID(updatedTrackIndex(indexmapping, hit.GetTrackID()));
356 }
357 }
358 }
359
360 void attachHits(fair::mq::Channel& channel, fair::mq::Parts& parts) override
361 {
362 int probe = 0;
363 // check if there is anything to be attached
364 // at least the first hit index should return non nullptr
365 if (static_cast<Det*>(this)->Det::getHits(0) == nullptr) {
366 return;
367 }
368
369 // decide the transport once, so that the header and all hit messages agree
371 attachHitsHeaderMessage({GetDetId(), shm}, channel, parts); // the DetId s are universal as they come from o2::detector::DetID
372
373 while (auto hits = static_cast<Det*>(this)->Det::getHits(probe++)) {
374 if (!shm) {
375 attachTMessage(*hits, channel, parts);
376 } else {
377 // this is the shared mem variant
378 // we will just send the sharedmem ID and the offset inside
379 *mShmBusy[mCurrentBuffer] = true;
380 attachShmMessage((void*)hits, channel, parts, mShmBusy[mCurrentBuffer]);
381 }
382 }
383 }
384
385 // this merges several entries from the TBranch brname from the origin TTree
386 // into a single entry in a target TTree / same branch
387 // (assuming T is typically a vector; merging is simply done by appending)
388 // make this function a (static helper)
389 template <typename T>
390 void mergeAndAdjustHits(std::string const& brname, TTree& origin, TTree& target,
391 std::vector<int> const& trackoffsets, std::vector<int> const& nprimaries, std::vector<int> const& subevtsOrdered)
392 {
393 auto originbr = origin.GetBranch(brname.c_str());
394 if (originbr) {
395 auto targetdata = new T;
396 T* incomingdata = nullptr;
397 originbr->SetAddress(&incomingdata);
398
399 T* filladdress = nullptr;
400 if (origin.GetEntries() == 1) {
401 originbr->GetEntry(0);
402 filladdress = incomingdata;
403 } else {
404 Int_t entries = origin.GetEntries();
405 Int_t nprimTot = 0;
406 for (auto entry = 0; entry < entries; entry++) {
407 nprimTot += nprimaries[entry];
408 }
409 // offset for pimary track index
410 Int_t idelta0 = 0;
411 // offset for secondary track index
412 Int_t idelta1 = nprimTot;
413 for (int entry = entries - 1; entry >= 0; --entry) {
414 // proceed in the order of subevent Ids
415 Int_t index = subevtsOrdered[entry];
416 // numbe of primaries for this event
417 Int_t nprim = nprimaries[index];
418 idelta1 -= nprim;
419 filladdress = targetdata;
420 originbr->GetEntry(index);
421 if (incomingdata) {
422 // fix the trackIDs for this data
423 for (auto& hit : *incomingdata) {
424 hit.SetTrackID(offsetTrackIndex(hit.GetTrackID(), nprim, idelta0, idelta1));
425 }
426 // this could be further generalized by using a policy for T
427 std::copy(incomingdata->begin(), incomingdata->end(), std::back_inserter(*targetdata));
428 delete incomingdata;
429 incomingdata = nullptr;
430 }
431 // adjust offsets for next subevent
432 idelta0 += nprim;
433 idelta1 += trackoffsets[index];
434 } // subevent loop
435 }
436 // fill target for this event
437 auto targetbr = o2::base::getOrMakeBranch(target, brname.c_str(), &filladdress);
438 targetbr->SetAddress(&filladdress);
439 targetbr->Fill();
440 targetbr->ResetAddress();
441 targetdata->clear();
442 if (incomingdata) {
443 delete incomingdata;
444 incomingdata = nullptr;
445 }
446 delete targetdata;
447 }
448 }
449
450 // this merges several entries from temporary hit buffer into
451 // into a single entry in a target TTree / same branch
452 // (assuming T is typically a vector; merging is simply done by appending)
453 template <typename T, typename L>
454 void mergeAndAdjustHits(std::string const& brname, L& hitbuffervector, TTree& target,
455 std::vector<int> const& trackoffsets, std::vector<int> const& nprimaries,
456 std::vector<int> const& subevtsOrdered)
457 {
458 auto entries = hitbuffervector.size();
459
460 T targetdata; // used to collect data inside a single container
461 T* filladdress = nullptr; // pointer used for final ROOT IO
462 if (entries == 1) {
463 filladdress = hitbuffervector[0].get();
464 // nothing to do; we can directly do IO from the existing buffer
465 } else {
466 // here we need to do merging and index adjustment
467 int nprimTot = 0;
468 size_t nhits = 0;
469 for (auto entry = 0; entry < entries; entry++) {
470 nprimTot += nprimaries[entry];
471 nhits += hitbuffervector[entry] ? hitbuffervector[entry]->size() : 0;
472 }
473 targetdata.reserve(nhits);
474 // offset for pimary track index
475 int idelta0 = 0;
476 // offset for secondary track index
477 int idelta1 = nprimTot;
478 filladdress = &targetdata;
479 for (int entry = entries - 1; entry >= 0; --entry) {
480 // proceed in the order of subevent Ids
481 int index = subevtsOrdered[entry];
482 // number of primaries for this event
483 int nprim = nprimaries[index];
484 idelta1 -= nprim;
485
486 // fetch correct data item
487 auto incomingdata = hitbuffervector[index].get();
488 if (incomingdata) {
489 // fix the trackIDs for this data
490 for (auto& hit : *incomingdata) {
491 hit.SetTrackID(offsetTrackIndex(hit.GetTrackID(), nprim, idelta0, idelta1));
492 }
493 // move rather than copy, since hits may own memory themselves (e.g. TPC HitGroup)
494 targetdata.insert(targetdata.end(), std::make_move_iterator(incomingdata->begin()), std::make_move_iterator(incomingdata->end()));
495 }
496 // adjust offsets for next subevent
497 idelta0 += nprim;
498 idelta1 += trackoffsets[index];
499 } // subevent loop
500 }
501 // fill target for this event
502 auto targetbr = o2::base::getOrMakeBranch(target, brname.c_str(), &filladdress);
503 targetbr->SetAddress(&filladdress);
504 targetbr->Fill();
505 targetbr->ResetAddress();
506 hitbuffervector = L(); // swap with empty vector to release mem
507 }
508
509 void mergeHitEntries(TTree& origin, TTree& target, std::vector<int> const& trackoffsets, std::vector<int> const& nprimaries, std::vector<int> const& subevtsOrdered) final
510 {
511 // loop over hit containers / different branches
512 // adjust trackID in hits on the go
513 int probe = 0;
514 using Hit_t = decltype(static_cast<Det*>(this)->Det::getHits(probe));
515 std::string name = static_cast<Det*>(this)->getHitBranchNames(probe++);
516 while (name.size() > 0) {
517 mergeAndAdjustHits<typename std::remove_pointer<Hit_t>::type>(name, origin, target, trackoffsets, nprimaries, subevtsOrdered);
518 // next name
519 name = static_cast<Det*>(this)->getHitBranchNames(probe++);
520 }
521 }
522
523 // the hit containers buffered in the hit merger, per event and per hit branch
525 {
526 using Hit_t = typename std::remove_pointer<decltype(static_cast<Det*>(this)->Det::getHits(0))>::type;
527 using Collector_t = tbb::concurrent_unordered_map<int, std::vector<std::vector<std::unique_ptr<Hit_t>>>>;
528 if (!mHitCollector) {
529 mHitCollector = std::make_shared<Collector_t>();
530 }
531 return *static_cast<Collector_t*>(mHitCollector.get());
532 }
533
534 void mergeHitEntriesAndFlush(int eventID, TTree& target, std::vector<int> const& trackoffsets, std::vector<int> const& nprimaries, std::vector<int> const& subevtsOrdered) final
535 {
536 // loop over hit containers / different branches
537 // adjust trackID in hits on the go
538 int probe = 0;
539 using Hit_t = typename std::remove_pointer<decltype(static_cast<Det*>(this)->Det::getHits(0))>::type;
540 // remove buffered event from the hit store
541 auto& collector = hitCollector();
542 auto iter = collector.find(eventID);
543 if (iter == collector.end()) {
544 LOG(error) << "No buffered hits available for event " << eventID;
545 return;
546 }
547
548 std::string name = static_cast<Det*>(this)->getHitBranchNames(probe);
549 while (name.size() > 0) {
550 auto& vectorofHitBuffers = (*iter).second[probe];
551 // flushing and buffer removal is done inside here:
552 mergeAndAdjustHits<Hit_t>(name, vectorofHitBuffers, target, trackoffsets, nprimaries, subevtsOrdered);
553 // next name
554 probe++;
555 name = static_cast<Det*>(this)->getHitBranchNames(probe);
556 }
557 }
558
559 public:
563 void collectHits(int eventID, fair::mq::Parts& parts, int& index, bool shm) override
564 {
565 using Hit_t = typename std::remove_pointer<decltype(static_cast<Det*>(this)->Det::getHits(0))>::type;
566 auto& hitcollector = hitCollector();
567
568 int probe = 0;
569 ShmBusyFlag* busy = nullptr;
570 using HitPtr_t = decltype(static_cast<Det*>(this)->Det::getHits(probe));
571 std::string name = static_cast<Det*>(this)->getHitBranchNames(probe);
572
573 // stores one hit container of this event and probe in the collector
574 auto store = [eventID, &hitcollector](std::unique_ptr<Hit_t> hits, int probe) {
575 auto& hitvector = hitcollector[eventID]; // tbb insertion is thread-safe
576 if (probe >= hitvector.size()) {
577 hitvector.resize(probe + 1);
578 }
579 hitvector[probe].emplace_back(std::move(hits));
580 };
581
582 while (name.size() > 0) {
583 if (!shm) {
584 // a decoded TMessage is ours, so we adopt it
585 if (auto hitsptr = decodeTMessage<HitPtr_t>(parts, index++)) {
586 store(std::unique_ptr<Hit_t>(hitsptr), probe);
587 }
588 } else {
589 // hits in shared memory belong to the worker, so we copy them
590 auto hitsptr = decodeShmMessage<HitPtr_t>(parts, index++, busy);
591 store(std::make_unique<Hit_t>(*hitsptr), probe);
592 }
593 // next name
594 probe++;
595 name = static_cast<Det*>(this)->getHitBranchNames(probe);
596 }
597 // there is only one busy flag per detector so we need to clear it only
598 // at the end (after all branches have been treated)
599 if (busy) {
600 *busy = false;
601 }
602 }
603
604 void fillHitBranch(TTree& tr, fair::mq::Parts& parts, int& index) override
605 {
606 int probe = 0;
607 ShmBusyFlag* busy = nullptr;
608 using Hit_t = decltype(static_cast<Det*>(this)->Det::getHits(probe));
609 std::string name = static_cast<Det*>(this)->getHitBranchNames(probe++);
610 while (name.size() > 0) {
612
613 // for each branch name we extract/decode hits from the message parts ...
614 auto hitsptr = decodeTMessage<Hit_t>(parts, index++);
615 if (hitsptr) {
616 // ... and fill the tree branch
617 auto br = getOrMakeBranch(tr, name.c_str(), hitsptr);
618 br->SetAddress(static_cast<void*>(&hitsptr));
619 br->Fill();
620 br->ResetAddress();
621 delete hitsptr;
622 }
623 } else {
624 // for each branch name we extract/decode hits from the message parts ...
625 auto hitsptr = decodeShmMessage<Hit_t>(parts, index++, busy);
626 // ... and fill the tree branch
627 auto br = getOrMakeBranch(tr, name.c_str(), hitsptr);
628 br->SetAddress(static_cast<void*>(&hitsptr));
629 br->Fill();
630 br->ResetAddress();
631 }
632 // next name
633 name = static_cast<Det*>(this)->getHitBranchNames(probe++);
634 }
635 // there is only one busy flag per detector so we need to clear it only
636 // at the end (after all branches have been treated)
637 if (busy) {
638 *busy = false;
639 }
640 }
641
642 // implementing CloneModule (for G4-MT mode) automatically for each deriving
643 // Detector class "Det"; calls copy constructor of Det
644 FairModule* CloneModule() const final
645 {
646 return new Det(static_cast<const Det&>(*this));
647 }
648
650 {
651 using Hit_t = decltype(static_cast<Det*>(this)->Det::getHits(0));
652 if (UseShm<Det>::value) {
653 for (int buffer = 0; buffer < NHITBUFFERS; ++buffer) {
654 for (auto ptr : mCachedPtr[buffer]) {
655 o2::utils::freeSimVector(static_cast<Hit_t>(ptr));
656 }
657 }
658 }
659 }
660
661 // default implementation for setting hits
662 // always returns false indicating that there is no other
663 // component to assign to apart from i == 0
664 template <typename Hit_t>
665 bool setHits(int i, std::vector<Hit_t>* ptr)
666 {
667 if (i == 0) {
668 static_cast<Det*>(this)->Det::mHits = ptr;
669 }
670 return false;
671 }
672
673 // creating a number of hit buffers (in shared mem) -- to which
674 // detectors can write in round-robin fashion
676 {
677 using VectorHit_t = decltype(static_cast<Det*>(this)->Det::getHits(0));
678 using Hit_t = typename std::remove_pointer<VectorHit_t>::type::value_type;
679 for (int buffer = 0; buffer < NHITBUFFERS; ++buffer) {
680 int probe = 0;
681 bool more{false};
682 do {
683 auto ptr = o2::utils::createSimVector<Hit_t>();
684 more = static_cast<Det*>(this)->Det::setHits(probe, ptr);
685 mCachedPtr[buffer].emplace_back(ptr);
686 probe++;
687 } while (more);
688 }
689 }
690
691 void initializeLate() final
692 {
693 if (!mInitialized) {
694 if (UseShm<Det>::value) {
695 static_cast<Det*>(this)->Det::createHitBuffers();
696 for (int b = 0; b < NHITBUFFERS; ++b) {
697 auto& instance = o2::utils::ShmManager::Instance();
698 mShmBusy[b] = instance.hasSegment() ? new (instance.getmemblock(sizeof(ShmBusyFlag))) ShmBusyFlag(false) : new ShmBusyFlag(false);
699 }
700 }
701 mInitialized = true;
702 mCurrentBuffer = 0;
703 }
704 }
705
706 void BeginEvent() final
707 {
708 if (UseShm<Det>::value) {
710 while (mShmBusy[mCurrentBuffer] != nullptr && *mShmBusy[mCurrentBuffer]) {
711 // this should ideally never happen
712 LOG(info) << " BUSY WAITING SIZE ";
713 sleep(1);
714 }
715
716 using Hit_t = decltype(static_cast<Det*>(this)->Det::getHits(0));
717
718 // now we have to clear the hits before writing again
719 int probe = 0;
720 for (auto bareptr : mCachedPtr[mCurrentBuffer]) {
721 auto hits = static_cast<Hit_t>(bareptr);
722 // assign ..
723 static_cast<Det*>(this)->Det::setHits(probe, hits);
724 hits->clear();
725 probe++;
726 }
727 }
728 }
729
730 ~DetImpl() override
731 {
732 for (int i = 0; i < NHITBUFFERS; ++i) {
733 if (mShmBusy[i]) {
734 auto& instance = o2::utils::ShmManager::Instance();
735 if (instance.hasSegment()) {
736 instance.freememblock(mShmBusy[i]);
737 } else {
738 delete mShmBusy[i];
739 }
740 }
741 }
743 }
744
745 protected:
746 static constexpr int NHITBUFFERS = 3; // number of buffers for hits in order to allow async processing
747 // in the hit merger without blocking nor copying the data
748 // (like done in typical data aquisition systems)
750 std::vector<void*> mCachedPtr[NHITBUFFERS];
751 int mCurrentBuffer = 0; // holding the current buffer information
752 int mInitialized = false;
753
754 std::shared_ptr<void> mHitCollector;
755
757};
758} // namespace o2::base
759
760#endif
header::DataOrigin origin
std::vector< long > entries
int32_t i
uint32_t res
Definition RawData.h:0
TBranch * ptr
void freeHitBuffers()
Definition Detector.h:649
~DetImpl() override
Definition Detector.h:730
void updateHitTrackIndices(std::map< int, int > const &indexmapping) override
Definition Detector.h:349
std::shared_ptr< void > mHitCollector
Definition Detector.h:754
void mergeHitEntriesAndFlush(int eventID, TTree &target, std::vector< int > const &trackoffsets, std::vector< int > const &nprimaries, std::vector< int > const &subevtsOrdered) final
Definition Detector.h:534
std::vector< void * > mCachedPtr[NHITBUFFERS]
pointer to flag in shared mem indicating of IO busy
Definition Detector.h:750
auto & hitCollector()
Definition Detector.h:524
std::string getHitBranchNames(int probe) const override
Definition Detector.h:338
void collectHits(int eventID, fair::mq::Parts &parts, int &index, bool shm) override
Definition Detector.h:563
static constexpr int NHITBUFFERS
Definition Detector.h:746
void fillHitBranch(TTree &tr, fair::mq::Parts &parts, int &index) override
Definition Detector.h:604
void createHitBuffers()
Definition Detector.h:675
void BeginEvent() final
Definition Detector.h:706
void attachHits(fair::mq::Channel &channel, fair::mq::Parts &parts) override
Definition Detector.h:360
void mergeAndAdjustHits(std::string const &brname, TTree &origin, TTree &target, std::vector< int > const &trackoffsets, std::vector< int > const &nprimaries, std::vector< int > const &subevtsOrdered)
Definition Detector.h:390
void mergeAndAdjustHits(std::string const &brname, L &hitbuffervector, TTree &target, std::vector< int > const &trackoffsets, std::vector< int > const &nprimaries, std::vector< int > const &subevtsOrdered)
Definition Detector.h:454
bool setHits(int i, std::vector< Hit_t > *ptr)
Definition Detector.h:665
ShmBusyFlag * mShmBusy[NHITBUFFERS]
Definition Detector.h:749
FairModule * CloneModule() const final
Definition Detector.h:644
void initializeLate() final
Definition Detector.h:691
void mergeHitEntries(TTree &origin, TTree &target, std::vector< int > const &trackoffsets, std::vector< int > const &nprimaries, std::vector< int > const &subevtsOrdered) final
Definition Detector.h:509
ClassDefOverride(DetImpl, 0)
type-erased hit buffers of this instance in the hit merger (see hitCollector())
virtual std::string getHitBranchNames(int probe) const =0
void SpecialProcess(Int_t numed, EProc parID, int val)
Set process by name and value.
Definition Detector.cxx:98
int registerSensitiveVolumeAndGetVolID(std::string const &name)
Definition Detector.cxx:190
~Detector() override
Default Destructor.
Definition Detector.cxx:95
static std::vector< int > const & getDetId2HitBitIndex()
Definition Detector.h:241
virtual void initializeLate()=0
Detector & operator=(const Detector &)
Definition Detector.cxx:46
virtual void defineLayerTurbo(Int_t nlay, Double_t phi0, Double_t r, Int_t nladd, Int_t nmod, Double_t width, Double_t tilt, Double_t lthick=0., Double_t dthick=0., UInt_t detType=0, Int_t buildFlag=0)
Definition Detector.cxx:117
TClonesArray * GetCollection(int iColl) const final
Definition Detector.cxx:162
virtual void attachHits(fair::mq::Channel &, fair::mq::Parts &)=0
virtual void fillParallelWorld() const
fill parallel geometry with sensitive volumes of detector
Definition Detector.cxx:174
void Initialize() final
Definition Detector.h:210
int getMaterialID(int imat) const
Definition Detector.h:128
void getMediumIDMappingAsVector(std::vector< int > &mapping)
Definition Detector.h:144
static void setDensityFactor(Float_t density)
Definition Detector.h:93
static int updatedTrackIndex(std::map< int, int > const &indexmapping, int trackID)
Definition Detector.h:169
void SpecialCuts(Int_t numed, const std::initializer_list< std::pair< ECut, Float_t > > &parIDValMap)
Custom processes and transport cuts.
Definition Detector.cxx:80
void SpecialCut(Int_t numed, ECut parID, Float_t val)
Set cut by name and value.
Definition Detector.cxx:86
void SpecialProcesses(Int_t numed, const std::initializer_list< std::pair< EProc, int > > &parIDValMap)
Definition Detector.cxx:92
void Matrix(Int_t &nmat, Double_t theta1, Double_t phi1, Double_t theta2, Double_t phi2, Double_t theta3, Double_t phi3) const
Definition Detector.cxx:104
Detector()
Default Constructor.
Definition Detector.cxx:36
virtual void setNumberOfWrapperVolumes(Int_t n)
Books arrays for wrapper volumes.
Definition Detector.cxx:111
virtual void updateHitTrackIndices(std::map< int, int > const &)=0
virtual void mergeHitEntries(TTree &origin, TTree &target, std::vector< int > const &trackoffsets, std::vector< int > const &nprimaries, std::vector< int > const &subevtsOrdered)=0
virtual void collectHits(int eventID, fair::mq::Parts &parts, int &index, bool shm)=0
void Mixture(Int_t imat, const char *name, Float_t *a, Float_t *z, Float_t dens, Int_t nlmat, Float_t *wmat)
Definition Detector.cxx:66
virtual void addAlignableVolumes() const
declare alignable volumes of detector
Definition Detector.cxx:169
void Medium(Int_t numed, const char *name, Int_t nmat, Int_t isvol, Int_t ifield, Float_t fieldm, Float_t tmaxfd, Float_t stemax, Float_t deemax, Float_t epsil, Float_t stmin, Float_t *ubuf=nullptr, Int_t nbuf=0)
Definition Detector.cxx:72
void SetSpecialPhysicsCuts() override
Definition Detector.cxx:122
static Float_t getDensityFactor()
Definition Detector.h:98
int getMediumID(int imed) const
Definition Detector.h:136
virtual void fillHitBranch(TTree &tr, fair::mq::Parts &parts, int &index)=0
static void setDetId2HitBitIndex(std::vector< int > const &v)
set the DetID to HitBitIndex mapping. Succeeds if not already set.
Definition Detector.h:240
static void initFieldTrackingParams(int &mode, float &maxfield)
Definition Detector.cxx:143
virtual void defineWrapperVolume(Int_t id, Double_t rmin, Double_t rmax, Double_t zspan)
Sets per wrapper volume parameters.
Definition Detector.cxx:110
virtual void defineLayer(Int_t nlay, Double_t phi0, Double_t r, Int_t nladd, Int_t nmod, Double_t lthick=0., Double_t dthick=0., UInt_t detType=0, Int_t buildFlag=0)
virtual void mergeHitEntriesAndFlush(int eventID, TTree &target, std::vector< int > const &trackoffsets, std::vector< int > const &nprimaries, std::vector< int > const &subevtsOrdered)=0
static int offsetTrackIndex(int trackID, int nprimaries, int primaryOffset, int secondaryOffset)
Definition Detector.h:178
void Material(Int_t imat, const char *name, Float_t a, Float_t z, Float_t dens, Float_t radl, Float_t absl, Float_t *buf=nullptr, Int_t nwbuf=0)
Definition Detector.cxx:59
std::string addNameTo(const char *ext) const
Definition Detector.h:151
virtual void InitializeO2Detector()=0
Definition Detector.cxx:106
static MaterialManager & Instance()
static ShmManager & Instance()
Definition ShmManager.h:61
bool isOperational() const
Definition ShmManager.h:97
GLdouble n
Definition glcorearb.h:1982
GLenum mode
Definition glcorearb.h:266
GLuint buffer
Definition glcorearb.h:655
GLuint entry
Definition glcorearb.h:5735
const GLdouble * v
Definition glcorearb.h:832
GLuint index
Definition glcorearb.h:781
GLuint const GLchar * name
Definition glcorearb.h:781
GLint GLsizei width
Definition glcorearb.h:270
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLenum target
Definition glcorearb.h:1641
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLboolean * data
Definition glcorearb.h:298
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLuint GLfloat * val
Definition glcorearb.h:1582
GLboolean r
Definition glcorearb.h:1233
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glcorearb.h:2514
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
ECut
cuts available
void * decodeShmCore(fair::mq::Parts &dataparts, int index, ShmBusyFlag *&busy)
Definition Detector.cxx:240
EProc
processes available
void attachShmMessage(void *hitsptr, fair::mq::Channel &channel, fair::mq::Parts &parts, ShmBusyFlag *busy_ptr)
Definition Detector.cxx:223
void * decodeTMessageCore(fair::mq::Parts &dataparts, int index)
Definition Detector.cxx:255
std::atomic< bool > ShmBusyFlag
Definition Detector.h:274
TBranch * getOrMakeBranch(TTree &tree, const char *brname, T *ptr)
Definition Detector.h:310
void attachMessageBufferToParts(fair::mq::Parts &parts, fair::mq::Channel &channel, void *data, TClass *cl)
Definition Detector.cxx:207
void attachTMessage(Container const &hits, fair::mq::Channel &channel, fair::mq::Parts &parts)
Definition Detector.h:289
void attachHitsHeaderMessage(HitsHeader const &header, fair::mq::Channel &channel, fair::mq::Parts &parts)
Definition Detector.cxx:218
std::string demangle(const char *name)
utility function to demangle cxx type names
Definition Detector.h:266
T decodeShmMessage(fair::mq::Parts &dataparts, int index, ShmBusyFlag *&busy)
Definition Detector.h:280
T decodeTMessage(fair::mq::Parts &dataparts, int index)
Definition Detector.h:296
void freeSimVector(std::vector< T > *ptr)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))