BmnRoot
Loading...
Searching...
No Matches
BmnNdet.cxx
Go to the documentation of this file.
1#include "BmnNdet.h"
2
3#include "BmnNdetCell.h"
5#include "CbmStack.h"
6#include "FairRootManager.h"
7#include "FairRun.h"
8#include "FairRuntimeDb.h"
9#include "FairVolume.h"
10#include "TGeoManager.h"
11#include "TLorentzVector.h"
12#include "TParticle.h"
13#include "TVirtualMC.h"
14
15#include <iostream>
16
18 : FairDetector("BmnNdet", true)
19 , fGeoHandler(new BmnNdetGeo())
20 , fCollection(new TClonesArray("BmnNdetPoint"))
21 , fSurfaceCollection(new TClonesArray("BmnNdetSurfacePoint"))
22{
23 LOG(debug4) << "BmnNdet default constructor called";
24}
25
26BmnNdet::BmnNdet(const char* name, Bool_t active)
27 : FairDetector(name, active)
28 , fGeoHandler(new BmnNdetGeo())
29 , fCollection(new TClonesArray("BmnNdetPoint"))
30 , fSurfaceCollection(new TClonesArray("BmnNdetSurfacePoint"))
31{
32 LOG(debug4) << "BmnNdet constructor called with name: " << name << " and active: " << active;
33}
34
36{
37 LOG(debug4) << "BmnNdet destructor called";
38 if (fCollection) {
39 fCollection->Delete();
40 delete fCollection;
41 }
42 if (fSurfaceCollection) {
43 fSurfaceCollection->Delete();
44 delete fSurfaceCollection;
45 }
46 delete fGeoHandler;
47}
48
50{
51 LOG(debug4) << "BmnNdet Initialize method called";
52 FairDetector::Initialize();
53 // FairRun* sim = FairRun::Instance();
54 // FairRuntimeDb* rtdb = sim->GetRuntimeDb();
55}
56
58{
59 LOG(debug4) << "BmnNdet BeginEvent method called";
60}
61
62Int_t BmnNdet::FindHitIndex(int trackID, uint32_t address)
63{
64 LOG(debug4) << "BmnNdet FindHitIndex method called for (trackID, address): (" << trackID << ", " << address << ")";
65 // almost guaranteed that each time we need last entry, therefore search backwards
66 for (Int_t i = fCollection->GetEntriesFast() - 1; i >= 0; i--) {
67 auto* ThisPoint = static_cast<BmnNdetPoint*>(fCollection->At(i));
68 if (ThisPoint->GetTrackID() == trackID && ThisPoint->GetAddress() == address) {
69 return i; // Return the index if a match is found
70 }
71 }
72
73 return -1; // Return -1 if no match is found
74}
75
76BmnNdetPoint* BmnNdet::GetHit(int trackID, uint32_t address)
77{
78 auto index = FindHitIndex(trackID, address);
79 if (index >= 0)
80 return static_cast<BmnNdetPoint*>(fCollection->At(index));
81 else
82 return nullptr;
83}
84
85double GetBirkQCF()
86{
87 LOG(debug4) << "GetBirkQCF function called";
88 const double BirkConst = 12.6; // (12.6 cm/GeV - from Wikipedia, 0.07943mm/MeV in Geant4)
89 double QCF = 1.0 + (BirkConst / gMC->TrackStep()) * gMC->Edep();
90 return QCF;
91}
92
93Bool_t BmnNdet::ProcessHits(FairVolume* vol)
94{
95 LOG(debug4) << "BmnNdet ProcessHits method called for event " << gMC->CurrentEvent();
96 Int_t trackID = gMC->GetStack()->GetCurrentTrackNumber();
97
98 if (CheckIfVacuum()) {
99 if (gMC->IsTrackEntering()) {
100 LOG(debug4) << "BmnNdet::ProcessHits: vacuum" << gMC->CurrentVolName() << " " << gMC->CurrentVolPath();
101 TLorentzVector tPos, tMom;
102 gMC->TrackPosition(tPos);
103 gMC->TrackMomentum(tMom);
104 TVector3 pos = TVector3(tPos.X(), tPos.Y(), tPos.Z());
105 TVector3 mom = TVector3(tMom.X(), tMom.Y(), tMom.Z());
106 auto [planeId, direction] = fGeoHandler->GetEnteredFace(pos, mom);
107 uint8_t armID = fGeoHandler->GetArmFromPath(gMC->CurrentVolPath());
108
109 new ((*fSurfaceCollection)[fSurfaceCollection->GetEntriesFast()])
110 BmnNdetSurfacePoint(gMC->GetStack()->GetCurrentTrackNumber(), pos, mom, gMC->TrackTime() * 1.0e09,
111 gMC->TrackLength(), gMC->TrackPid(), gMC->CurrentEvent(), armID,
112 static_cast<uint8_t>(planeId), static_cast<uint8_t>(direction));
113
114 ((CbmStack*)gMC->GetStack())->AddPoint(kNDET);
115 }
116 return kTRUE;
117 }
118
119 if (!CheckIfSensitive(gMC->CurrentVolName()) || gMC->Edep() < 0) {
120 return kFALSE;
121 }
122
123 uint32_t address = fGeoHandler->GetAddressFromPath(gMC->CurrentVolPath());
124
125 // new track is entering sensitive volume for the first time
126 if (GetHit(trackID, address) == nullptr) {
127 LOG(debug4) << "trackID = " << trackID << " entering. " << BmnNdetAddress::GetInfoString(address)
128 << ". Edep = " << gMC->Edep() << " Time = " << gMC->TrackTime() * 1.0e09;
129 if (!gMC->IsTrackEntering())
130 LOG(warning) << "trackID = " << trackID << " is not marked as gMC->IsTrackEntering() ";
131
132 // Initializing new hit
133 BmnNdetPoint* newPoint = new BmnNdetPoint();
134 newPoint->ResetLinks();
135 newPoint->SetEventID(gMC->CurrentEvent());
136 newPoint->SetTrackID(trackID);
137 newPoint->SetAddress(address);
138 TLorentzVector tPos, tMom;
139 gMC->TrackPosition(tPos); // Position at entrance
140 gMC->TrackMomentum(tMom); // Momentum at entrance
141 newPoint->SetPosition(TVector3(tPos.X(), tPos.Y(), tPos.Z()));
142 newPoint->SetMomentum(TVector3(tMom.X(), tMom.Y(), tMom.Z()));
143
144 double dEdep = (gMC->TrackCharge() != 0 && gMC->TrackStep() > 0) ? gMC->Edep() / GetBirkQCF()
145 : gMC->Edep(); // Energy loss at current step
146 newPoint->SetEnergyLoss(dEdep);
147 newPoint->SetTime(gMC->TrackTime() * 1.0e09); // Time of flight
148 newPoint->SetLength(gMC->TrackLength()); // Length of the current track from its origin (in cm)
149
150 // Inserting new hit
151 AddHit(newPoint);
152 } else { // Increment hit properties of this track
153 double dEdep = (gMC->TrackCharge() != 0 && gMC->TrackStep() > 0) ? gMC->Edep() / GetBirkQCF()
154 : gMC->Edep(); // Energy loss at current step
155 if (dEdep > std::numeric_limits<double>::epsilon()) {
156 LOG(debug4) << "BmnNdet::ProcessHits. trackID = " << trackID << " inside or exiting. "
157 << BmnNdetAddress::GetInfoString(address) << ". Edep = " << gMC->Edep()
158 << " Time = " << gMC->TrackTime() * 1.0e09;
159
160 BmnNdetPoint* point = GetHit(trackID, address);
161 double weighted_time = point->GetEnergyLoss() * point->GetTime() + dEdep * gMC->TrackTime() * 1.0e09;
162 point->SetEnergyLoss(point->GetEnergyLoss() + dEdep);
163 point->SetTime(weighted_time / point->GetEnergyLoss()); // Reweighted time of flight
164 }
165 }
166 // TODO handle reentering case differently if needed.
167 // gMC->IsTrackEntering() && GetHit(trackID, address) != nullptr
168
169 // last MC step for this track in this sens volume. If hit is zero-energy remove it from hits collection
170 if (gMC->IsTrackExiting() || gMC->IsTrackStop() || gMC->IsTrackDisappeared()) {
171 BmnNdetPoint* point = GetHit(trackID, address);
172 if (FinaliseTrackProcessing(point)) {
173 ((CbmStack*)gMC->GetStack())->AddPoint(kNDET);
174 auto surf_point = GetSurfacePoint(trackID);
175 if (surf_point >= 0)
176 point->AddLink(FairLink(static_cast<int>(BmnNdetCell::LinkType::SurfaceMCPoint), surf_point));
177 }
178 }
179
180 return kTRUE;
181}
182
184{
185 if (!point)
186 return false;
187 if (point->GetEnergyLoss() < std::numeric_limits<double>::epsilon()) {
188 LOG(debug4) << "BmnNdet ProcessHits: remove hit. trackID = " << point->GetTrackID() << " "
190 Int_t index = FindHitIndex(point->GetTrackID(), point->GetAddress());
191 RemoveHit(index);
192 return false;
193 }
194 return true;
195}
196
198{
199 LOG(debug4) << "BmnNdet EndOfEvent method called";
200 Print("");
201 Reset();
202}
203
205{
206 LOG(debug4) << "BmnNdet Register method called";
207 if (!FairRootManager::Instance()->GetObject("NdetPoint")) {
208 FairRootManager::Instance()->Register("NdetPoint", "Ndet", fCollection, kTRUE);
209 FairRootManager::Instance()->Register("NdetSurfacePoint", "Ndet", fSurfaceCollection, kTRUE);
210 } else
211 LOG(debug4) << "NdetPoint Already registered";
212}
213
214TClonesArray* BmnNdet::GetCollection(Int_t iColl) const
215{
216 LOG(debug4) << "BmnNdet GetCollection iColl=" << iColl;
217 if (iColl == 0)
218 return fCollection;
219 if (iColl == 1)
220 return fSurfaceCollection;
221 return nullptr;
222}
223
224void BmnNdet::Print(Option_t*) const
225{
226 LOG(debug4) << "BmnNdet Print method called";
227 Int_t nHits = fCollection->GetEntriesFast();
228 std::cout << "-I- BmnNdet: " << nHits << " points registered in event " << gMC->CurrentEvent() << std::endl;
229
230 if (FairLogger::GetLogger()->IsLogNeeded(fair::Severity::debug4)) {
231 for (Int_t i = 0; i < nHits; i++) {
232 (*fCollection)[i]->Print();
233 }
234 }
235}
236
238{
239 LOG(debug4) << "BmnNdet Reset method called";
240 fCollection->Delete();
241 fSurfaceCollection->Delete();
242}
243
245{
246 LOG(debug4) << "BmnNdet ConstructGeometry method called";
247 TString fileName = GetGeometryFileName();
248 if (fileName.EndsWith(".root")) {
249 LOG(info) << Form("Constructing NDET geometry from ROOT file %s", fileName.Data());
250 ConstructRootGeometry();
251 }
252
253 FairGeoLoader* geoLoad = FairGeoLoader::Instance();
254 FairGeoInterface* geoFace = geoLoad->getGeoInterface();
255 fGeoHandler->setGeomFile(GetGeometryFileName());
256 geoFace->addGeoModule(fGeoHandler);
257
258 Bool_t rc = geoFace->readSet(fGeoHandler);
259 if (rc)
260 fGeoHandler->create(geoLoad->getGeoBuilder());
261 TList* volList = fGeoHandler->getListOfVolumes();
262
263 // Store geo parameter
264 FairRun* fRun = FairRun::Instance();
265 FairRuntimeDb* rtdb = fRun->GetRuntimeDb();
266 BmnNdetGeoPar* par = (BmnNdetGeoPar*)(rtdb->getContainer("BmnNdetGeoPar"));
267 TObjArray* fSensNodes = par->GetGeoSensitiveNodes();
268 TObjArray* fPassNodes = par->GetGeoPassiveNodes();
269
270 TListIter iter(volList);
271 FairGeoNode* node = nullptr;
272
273 while ((node = (FairGeoNode*)iter.Next())) {
274 FairGeoVolume* aVol = dynamic_cast<FairGeoVolume*>(node);
275 if (node->isSensitive()) {
276 fSensNodes->AddLast(aVol);
277 LOG(debug4) << "BmnNdet ConstructGeometry add sensitive node " << aVol->GetName();
278 } else {
279 fPassNodes->AddLast(aVol);
280 LOG(debug4) << "BmnNdet ConstructGeometry add passive node " << aVol->GetName();
281 }
282 }
283 par->setChanged();
284 par->setInputVersion(fRun->GetRunId(), 1);
285
286 ProcessNodes(volList);
287}
288
289Bool_t BmnNdet::CheckIfSensitive(std::string name)
290{
291 LOG(debug4) << "BmnNdet CheckIfSensitive method called with name: " << name;
292 TString tsname = name.c_str();
295}
296
298{
299 return gMC->CurrentMedium() == gGeoManager->GetMedium("vacuum")->GetId();
300}
301
303{
304 TClonesArray& clref = *fCollection;
305 Int_t size = clref.GetEntriesFast();
306 return new (clref[size]) BmnNdetPoint(*point);
307}
308
309void BmnNdet::RemoveHit(Int_t index)
310{
311 if (index < 0 || index >= fCollection->GetEntriesFast()) {
312 LOG(debug4) << "BmnNdet RemoveHit method index: " << index << " out of range.";
313 return;
314 }
315 fCollection->RemoveAt(index);
316 fCollection->Compress(); // This method will remove NULL pointers from the array
317}
318
319int BmnNdet::GetSurfacePoint(int start_track_id)
320{
321 const auto* stack = static_cast<CbmStack*>(gMC->GetStack());
322 int current_id = start_track_id;
323
324 std::unordered_map<int, int> vacuum_map;
325 for (int i = 0, n = fSurfaceCollection->GetEntriesFast(); i < n; ++i) {
326 auto* pt = static_cast<BmnNdetSurfacePoint*>(fSurfaceCollection->UncheckedAt(i));
327 if (pt->GetDirectionID() == static_cast<int>(BmnNdetGeo::Direction::FromOutside))
328 vacuum_map[i] = pt->GetTrackID();
329 }
330
331 while (true) {
332 const TParticle* particle = stack->GetParticle(current_id);
333 if (!particle) {
334 LOG(error) << "BmnNdet::GetSurfacePoint. No particle with ID: " << current_id;
335 return -1;
336 }
337
338 for (const auto& [ipt, vac_track] : vacuum_map) {
339 if (vac_track == current_id) {
340 LOG(debug4) << "BmnNdet::GetSurfacePoint. Linked to " << vac_track;
341 return ipt;
342 }
343 }
344
345 if (particle->IsPrimary()) {
346 LOG(debug4) << Form("BmnNdet::GetSurfacePoint. Reached primary particle %d, no vacuum point found",
347 current_id);
348 return -1;
349 }
350
351 int mother_id = particle->GetFirstMother();
352 if (mother_id == current_id || mother_id < 0) {
353 LOG(error) << Form("BmnNdet::GetSurfacePoint. Invalid or circular mother link for track %d", current_id);
354 return -1;
355 }
356
357 current_id = mother_id;
358 }
359
360 return -1;
361}
double GetBirkQCF()
Definition BmnNdet.cxx:85
int i
Definition P4_F32vec4.h:22
@ kNDET
static std::string GetInfoString(uint32_t address)
Return a formatted string with all address components.
static const TString fEnvelopeVolumeName
TObjArray * GetGeoSensitiveNodes()
TObjArray * GetGeoPassiveNodes()
static const TString SensitiveVolume_name_VETO
static const TString SensitiveVolume_name_NICA
uint8_t GetArmFromPath(const std::string &spath) const
Definition BmnNdetGeo.h:64
static std::pair< BoxFace, Direction > GetEnteredFace(const TVector3 &globalPos, const TVector3 &globalMom)
Definition BmnNdetGeo.cxx:7
uint32_t GetAddressFromPath(const std::string &spath) const
Definition BmnNdetGeo.h:48
uint32_t GetAddress() const
void SetAddress(uint32_t address)
virtual Bool_t ProcessHits(FairVolume *vol=nullptr)
Definition BmnNdet.cxx:93
virtual ~BmnNdet()
Definition BmnNdet.cxx:35
Int_t FindHitIndex(int trackID, uint32_t address)
Definition BmnNdet.cxx:62
virtual void EndOfEvent()
Definition BmnNdet.cxx:197
BmnNdet()
Definition BmnNdet.cxx:17
BmnNdetPoint * AddHit(BmnNdetPoint *point)
Definition BmnNdet.cxx:302
virtual TClonesArray * GetCollection(Int_t iColl) const
Definition BmnNdet.cxx:214
virtual Bool_t CheckIfVacuum()
Definition BmnNdet.cxx:297
virtual Bool_t CheckIfSensitive(std::string name)
Definition BmnNdet.cxx:289
bool FinaliseTrackProcessing(BmnNdetPoint *point)
Definition BmnNdet.cxx:183
virtual void ConstructGeometry()
Definition BmnNdet.cxx:244
virtual void Reset()
Definition BmnNdet.cxx:237
virtual void Register()
Definition BmnNdet.cxx:204
int GetSurfacePoint(int start_track_id)
Definition BmnNdet.cxx:319
void RemoveHit(Int_t index)
Definition BmnNdet.cxx:309
BmnNdetPoint * GetHit(int trackID, uint32_t address)
Definition BmnNdet.cxx:76
virtual void Initialize()
Definition BmnNdet.cxx:49
virtual void BeginEvent()
Definition BmnNdet.cxx:57
virtual void Print(Option_t *) const
Definition BmnNdet.cxx:224