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