FairShip
Loading...
Searching...
No Matches
ShipStack.cxx
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-3.0-or-later
2// SPDX-FileCopyrightText: Copyright CERN for the benefit of the SHiP
3// Collaboration
4
5// -------------------------------------------------------------------------
6// ----- ShipStack source file -----
7// -------------------------------------------------------------------------
8#include "ShipStack.h"
9
10#include <iosfwd> // for ostream
11#include <iostream> // for operator<<, etc
12
13#include "FairDetector.h" // for FairDetector
14#include "FairLogger.h" // for FairLogger, MESSAGE_ORIGIN
15#include "FairMCPoint.h" // for FairMCPoint
16#include "FairRootManager.h" // for FairRootManager
17#include "ISTLPointContainer.h" // for STL-based detector interface
18#include "ShipMCTrack.h" // for ShipMCTrack
19#include "TClonesArray.h" // for TClonesArray
20#include "TIterator.h" // for TIterator
21#include "TLorentzVector.h" // for TLorentzVector
22#include "TParticle.h" // for TParticle
23#include "TRefArray.h" // for TRefArray
24#include "TVirtualMC.h"
25#include "TVirtualMCStack.h"
26
27using std::cout;
28using std::endl;
29using std::pair;
30
31// ----- Default constructor -------------------------------------------
33 : FairGenericStack(),
34 fStack(),
35 fParticles(new TClonesArray("TParticle", size)),
36 fTracks(nullptr),
37 fStoreMap(),
38 fStoreIter(),
39 fIndexMap(),
40 fIndexIter(),
41 fPointsMap(),
42 fCurrentTrack(-1),
43 fNPrimaries(0),
44 fNParticles(0),
45 fNTracks(0),
46 fIndex(0),
47 fStoreSecondaries(kTRUE),
48 fMinPoints(1),
49 fEnergyCut(0.),
50 fStoreMothers(kTRUE) {
51 fTracks = new std::vector<ShipMCTrack>();
52 fTracks->reserve(size);
53}
54
55// -------------------------------------------------------------------------
56
57// ----- Destructor ----------------------------------------------------
59 if (fParticles) {
60 fParticles->Delete();
61 delete fParticles;
62 }
63 if (fTracks) {
64 delete fTracks;
65 }
66}
67// -------------------------------------------------------------------------
68
69void ShipStack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode,
70 Double_t px, Double_t py, Double_t pz, Double_t e,
71 Double_t vx, Double_t vy, Double_t vz, Double_t time,
72 Double_t polx, Double_t poly, Double_t polz,
73 TMCProcess proc, Int_t& ntr, Double_t weight,
74 Int_t is) {
75 PushTrack(toBeDone, parentId, pdgCode, px, py, pz, e, vx, vy, vz, time, polx,
76 poly, polz, proc, ntr, weight, is, -1);
77}
78
79// ----- Virtual public method PushTrack -------------------------------
80void ShipStack::PushTrack(Int_t toBeDone, Int_t parentId, Int_t pdgCode,
81 Double_t px, Double_t py, Double_t pz, Double_t e,
82 Double_t vx, Double_t vy, Double_t vz, Double_t time,
83 Double_t polx, Double_t poly, Double_t polz,
84 TMCProcess proc, Int_t& ntr, Double_t weight,
85 Int_t is, Int_t secondparentID) {
86 // cout << "ShipStack: " << fNParticles << " " << pdgCode << " " << parentId
87 // << " " << secondparentID<<" "<<proc<< endl;
88
89 // --> Get TParticle array
90 TClonesArray& partArray = *fParticles;
91
92 // --> Create new TParticle and add it to the TParticle array
93 Int_t trackId = fNParticles;
94 Int_t nPoints = 0;
95 Int_t daughter1Id = -1;
96 Int_t daughter2Id = -1;
97 TParticle* particle = new (partArray[fNParticles++])
98 TParticle(pdgCode, trackId, parentId, nPoints, daughter1Id, daughter2Id,
99 px, py, pz, e, vx, vy, vz, time);
100 // from root, how does this fit ? misuse of status and mother2 ??? status is
101 // used for trackID definitely TParticle(Int_t pdg, Int_t status, Int_t
102 // mother1, Int_t mother2,
103 // Int_t daughter1, Int_t daughter2, Double_t px, Double_t py, Double_t pz,
104 // Double_t etot, Double_t vx, Double_t vy, Double_t vz, Double_t time)
105 particle->SetPolarisation(polx, poly, polz);
106 particle->SetWeight(weight);
107 particle->SetUniqueID(proc);
108 // TR August 2014, still trying to understand the logic of FairRoot, due to
109 // misuse of secondparentID, all is a big mess
110 if (parentId < 0) {
111 particle->SetFirstMother(secondparentID);
112 particle->SetLastMother(secondparentID);
113 } else {
114 particle->SetFirstMother(parentId);
115 particle->SetLastMother(parentId);
116 }
117 // --> Increment counter
118 if (parentId < 0) {
119 fNPrimaries++;
120 }
121
122 // --> Set argument variable
123 ntr = trackId;
124
125 // --> Push particle on the stack if toBeDone is set
126 if (toBeDone == 1) {
127 particle->SetBit(kDoneBit);
128 fStack.push(particle);
129 }
130}
131// -------------------------------------------------------------------------
132
133// ----- Virtual method PopNextTrack -----------------------------------
134TParticle* ShipStack::PopNextTrack(Int_t& iTrack) {
135 // If end of stack: Return empty pointer
136 if (fStack.empty()) {
137 iTrack = -1;
138 return nullptr;
139 }
140
141 // If not, get next particle from stack
142 TParticle* thisParticle = fStack.top();
143 fStack.pop();
144
145 if (!thisParticle) {
146 iTrack = 0;
147 return nullptr;
148 }
149
150 fCurrentTrack = thisParticle->GetStatusCode();
151 iTrack = fCurrentTrack;
152
153 return thisParticle;
154}
155// -------------------------------------------------------------------------
156
157// ----- Virtual method PopPrimaryForTracking --------------------------
158TParticle* ShipStack::PopPrimaryForTracking(Int_t iPrim) {
159 // Get the iPrimth particle from the fStack TClonesArray. This
160 // should be a primary (if the index is correct).
161
162 // Test for index
163 if (iPrim < 0 || iPrim >= fNPrimaries) {
164 LOGF(fatal, "ShipStack: Primary index out of range! %i ", iPrim);
165 }
166
167 // Return the iPrim-th TParticle from the fParticle array. This should be
168 // a primary.
169 TParticle* part = dynamic_cast<TParticle*>(fParticles->At(iPrim));
170 /* do not understand the logic behind this !!! TR July 2014
171 if ( ! (part->GetMother(0) < 0) ) {
172 fLogger->Fatal(MESSAGE_ORIGIN, "ShipStack:: Not a primary track! %i
173 ",iPrim); Fatal("ShipStack::PopPrimaryForTracking", "Not a primary track");
174 }*/
175 if (!part->TestBit(kDoneBit))
176 return nullptr;
177 else
178 return part;
179}
180// -------------------------------------------------------------------------
181
182// ----- Virtual public method GetCurrentTrack -------------------------
183TParticle* ShipStack::GetCurrentTrack() const {
184 TParticle* currentPart = GetParticle(fCurrentTrack);
185 if (!currentPart) {
186 LOG(warning) << "ShipStack: Current track not found in stack!";
187 }
188 return currentPart;
189}
190// -------------------------------------------------------------------------
191
192// ----- Public method AddParticle -------------------------------------
193void ShipStack::AddParticle(TParticle* oldPart) {
194 TClonesArray& array = *fParticles;
195 TParticle* newPart = new (array[fIndex]) TParticle(*oldPart);
196 newPart->SetWeight(oldPart->GetWeight());
197 newPart->SetUniqueID(oldPart->GetUniqueID());
198 fIndex++;
199}
200// -------------------------------------------------------------------------
201
202// ----- Public method FillTrackArray ----------------------------------
204 LOG(debug) << "ShipStack: Filling MCTrack array...";
205
206 // Some safeties to make sure everything exists
207 if (!gMC) return;
208 if (gMC->GetStack() == nullptr) return;
209
210 Int_t evtNo = -1;
211
212 // --> Reset index map and number of output tracks
213 fIndexMap.clear();
214 fNTracks = 0;
215
216 // --> Check tracks for selection criteria
217 SelectTracks();
218
219 if (fNParticles > 0) evtNo = gMC->CurrentEvent();
220
221 // --> Loop over fParticles array and copy selected tracks
222 for (Int_t iPart = 0; iPart < fNParticles; iPart++) {
223 fStoreIter = fStoreMap.find(iPart);
224 if (fStoreIter == fStoreMap.end()) {
225 LOGF(fatal, "ShipStack: Particle %i not found in storage map! ", iPart);
226 }
227 Bool_t store = (*fStoreIter).second;
228
229 if (store) {
230 fTracks->emplace_back(dynamic_cast<TParticle*>(GetParticle(iPart)));
231 ShipMCTrack& track = fTracks->back();
232 fIndexMap[iPart] = fNTracks;
233 // --> Set the number of points in the detectors for this track
234 for (Int_t iDet = kVETO; iDet < kEndOfList; iDet++) {
235 pair<Int_t, Int_t> a(iPart, iDet);
236 track.SetNPoints(iDet, fPointsMap[a]);
237 }
238 track.SetTrackID(fNTracks);
239 track.SetEventID(evtNo);
240 fNTracks++;
241 } else {
242 fIndexMap[iPart] = -2;
243 }
244 }
245
246 // --> Map index for primary mothers
247 fIndexMap[-1] = -1;
248
249 // --> Screen output
250 // Print(1);
251}
252// -------------------------------------------------------------------------
253
254// ----- Public method UpdateTrackIndex --------------------------------
255void ShipStack::UpdateTrackIndex(TRefArray* detList) {
256 LOG(debug) << "ShipStack: Updating track indizes...";
257 Int_t nColl = 0;
258
259 // First update mother ID in MCTracks
260 for (Int_t i = 0; i < fNTracks; i++) {
261 ShipMCTrack& track = (*fTracks)[i];
262 Int_t iMotherOld = track.GetMotherId();
263 fIndexIter = fIndexMap.find(iMotherOld);
264 if (fIndexIter == fIndexMap.end()) {
265 LOGF(fatal, "ShipStack: Particle index %i not found in dex map! ",
266 iMotherOld);
267 }
268 track.SetMotherId((*fIndexIter).second);
269 }
270
271 if (fDetList == 0) {
272 // Now iterate through all active detectors
273 fDetIter = detList->MakeIterator();
274 fDetIter->Reset();
275 } else {
276 fDetIter->Reset();
277 }
278
279 FairDetector* det = nullptr;
280 while ((det = dynamic_cast<FairDetector*>(fDetIter->Next()))) {
281 // --> Check if detector uses STL containers (std::vector)
282 if (auto* stlDet = dynamic_cast<ISTLPointContainer*>(det)) {
283 // Use new interface for STL-based detectors
284 stlDet->UpdatePointTrackIndices(fIndexMap);
285 nColl++;
286 } else {
287 // --> Get hit collections from detector (legacy TClonesArray approach)
288 Int_t iColl = 0;
289 TClonesArray* hitArray;
290 while ((hitArray = det->GetCollection(iColl++))) {
291 nColl++;
292 Int_t nPoints = hitArray->GetEntriesFast();
293
294 // --> Update track index for all MCPoints in the collection
295 for (Int_t iPoint = 0; iPoint < nPoints; iPoint++) {
296 FairMCPoint* point = dynamic_cast<FairMCPoint*>(hitArray->At(iPoint));
297 Int_t iTrack = point->GetTrackID();
298
299 fIndexIter = fIndexMap.find(iTrack);
300 if (fIndexIter == fIndexMap.end()) {
301 LOGF(fatal, "ShipStack: Particle index %i not found in index map! ",
302 iTrack);
303 }
304 point->SetTrackID((*fIndexIter).second);
305 }
306
307 } // Collections of this detector
308 }
309 } // List of active detectors
310 LOGF(debug, "...stack and %i collections updated.", nColl);
311}
312// -------------------------------------------------------------------------
313
314// ----- Public method Reset -------------------------------------------
316 fIndex = 0;
317 fCurrentTrack = -1;
319 while (!fStack.empty()) {
320 fStack.pop();
321 }
322 fParticles->Clear();
323 fTracks->clear();
324 fPointsMap.clear();
325}
326// -------------------------------------------------------------------------
327
328// ----- Public method Register ----------------------------------------
330 FairRootManager::Instance()->RegisterAny("MCTrack", fTracks, kTRUE);
331}
332// -------------------------------------------------------------------------
333
334// ----- Public method Print --------------------------------------------
335void ShipStack::Print(Int_t iVerbose) const {
336 cout << "-I- ShipStack: Number of primaries = " << fNPrimaries << endl;
337 cout << " Total number of particles = " << fNParticles << endl;
338 cout << " Number of tracks in output = " << fNTracks << endl;
339 if (iVerbose) {
340 for (Int_t iTrack = 0; iTrack < fNTracks; iTrack++) {
341 (*fTracks)[iTrack].Print(iTrack);
342 }
343 }
344}
345// -------------------------------------------------------------------------
346
347// ----- Public method AddPoint (for current track) --------------------
349 Int_t iDet = detId;
350 // cout << "Add point for Detektor" << iDet << endl;
351 pair<Int_t, Int_t> a(fCurrentTrack, iDet);
352 ++fPointsMap[a];
353}
354// -------------------------------------------------------------------------
355
356// ----- Public method AddPoint (for arbitrary track) -------------------
357void ShipStack::AddPoint(DetectorId detId, Int_t iTrack) {
358 if (iTrack < 0) {
359 return;
360 }
361 Int_t iDet = detId;
362 pair<Int_t, Int_t> a(iTrack, iDet);
363 ++fPointsMap[a];
364}
365// -------------------------------------------------------------------------
366
367// ----- Virtual method GetCurrentParentTrackNumber --------------------
369 TParticle* currentPart = GetCurrentTrack();
370 if (currentPart) {
371 return currentPart->GetFirstMother();
372 } else {
373 return -1;
374 }
375}
376// -------------------------------------------------------------------------
377
378// ----- Public method GetParticle -------------------------------------
379TParticle* ShipStack::GetParticle(Int_t trackID) const {
380 if (trackID < 0 || trackID >= fNParticles) {
381 LOGF(fatal, "ShipStack: Particle index %i out of range. Max=%i", trackID,
383 }
384 return dynamic_cast<TParticle*>(fParticles->At(trackID));
385}
386// -------------------------------------------------------------------------
387
388// ----- Private method SelectTracks -----------------------------------
390 // --> Clear storage map
391 fStoreMap.clear();
392
393 // --> Check particles in the fParticle array
394 for (Int_t i = 0; i < fNParticles; i++) {
395 TParticle* thisPart = GetParticle(i);
396 Bool_t store = kTRUE;
397
398 // --> Get track parameters
399 Int_t iMother = thisPart->GetMother(0);
400 TLorentzVector p;
401 thisPart->Momentum(p);
402 Double_t energy = p.E();
403 Double_t mass = p.M();
404 // Double_t mass = thisPart->GetMass();
405 Double_t eKin = energy - mass;
406
407 // --> Calculate number of points
408 Int_t nPoints = 0;
409 for (Int_t iDet = kVETO; iDet < kEndOfList; iDet++) {
410 pair<Int_t, Int_t> a(i, iDet);
411 if (fPointsMap.contains(a)) {
412 nPoints += fPointsMap[a];
413 }
414 }
415
416 // --> Check for cuts (store primaries in any case)
417 if (iMother < 0) {
418 store = kTRUE;
419 } else {
420 if (!fStoreSecondaries) {
421 store = kFALSE;
422 }
423 if (nPoints < fMinPoints) {
424 store = kFALSE;
425 }
426 if (eKin < fEnergyCut) {
427 store = kFALSE;
428 }
429 if ((nPoints >= fMinPoints && fMinPoints > 0) ||
430 (eKin >= fEnergyCut && fEnergyCut > 0)) {
431 store = kTRUE;
432 }
433 }
434 // --> Set storage flag
435 fStoreMap[i] = store;
436 // special case for Ship generators, want to keep all original particles
437 // with their mother daughter relationship independent if tracked or not.
438 // apply a dirty trick and use second mother to identify original generator
439 // particles. doesn't work, always true: Int_t iMother2 =
440 // GetParticle(i)->GetMother(1); maybe should set Mother2 to -1 in the
441 // generator if (iMother == iMother2) {fStoreMap[i] = kTRUE;}
442 }
443 // --> If flag is set, flag recursively mothers of selected tracks
444 if (fStoreMothers) {
445 for (Int_t i = 0; i < fNParticles; i++) {
446 if (fStoreMap[i]) {
447 Int_t iMother = GetParticle(i)->GetMother(0);
448 {
449 while (iMother >= 0) {
450 fStoreMap[iMother] = kTRUE;
451 iMother = GetParticle(iMother)->GetMother(0);
452 }
453 }
454 }
455 }
456 }
457}
458// -------------------------------------------------------------------------
const Int_t debug
DetectorId
@ kEndOfList
@ kVETO
@ kDoneBit
Definition: ShipStack.h:46
Interface for detectors using STL containers (std::vector) for MC points.
void SetTrackID(const Int_t &trackID)
void SetEventID(const Int_t &eventID)
void SetNPoints(Int_t iDet, Int_t np)
Int_t GetMotherId() const
Definition: ShipMCTrack.h:54
void SetMotherId(Int_t id)
Definition: ShipMCTrack.h:83
Int_t fMinPoints
Definition: ShipStack.h:203
Bool_t fStoreMothers
Definition: ShipStack.h:205
void AddPoint(DetectorId iDet)
Definition: ShipStack.cxx:348
Int_t GetCurrentParentTrackNumber() const override
Definition: ShipStack.cxx:368
std::map< std::pair< Int_t, Int_t >, Int_t > fPointsMap
Definition: ShipStack.h:192
void Register() override
Definition: ShipStack.cxx:329
~ShipStack() override
Definition: ShipStack.cxx:58
void PushTrack(Int_t toBeDone, Int_t parentID, Int_t pdgCode, Double_t px, Double_t py, Double_t pz, Double_t e, Double_t vx, Double_t vy, Double_t vz, Double_t time, Double_t polx, Double_t poly, Double_t polz, TMCProcess proc, Int_t &ntr, Double_t weight, Int_t is) override
Definition: ShipStack.cxx:69
Int_t fNTracks
Number of entries in fParticles.
Definition: ShipStack.h:198
void Reset() override
Definition: ShipStack.cxx:315
std::map< Int_t, Int_t > fIndexMap
Definition: ShipStack.h:188
TParticle * GetParticle(Int_t trackId) const
Definition: ShipStack.cxx:379
Int_t fIndex
Number of entries in fTracks.
Definition: ShipStack.h:199
TParticle * GetCurrentTrack() const override
Definition: ShipStack.cxx:183
virtual void Print(Int_t iVerbose=0) const
Definition: ShipStack.cxx:335
std::map< Int_t, Bool_t >::iterator fStoreIter
Definition: ShipStack.h:185
void UpdateTrackIndex(TRefArray *detArray=0) override
Definition: ShipStack.cxx:255
Double32_t fEnergyCut
Definition: ShipStack.h:204
void FillTrackArray() override
Definition: ShipStack.cxx:203
Bool_t fStoreSecondaries
Used for merging.
Definition: ShipStack.h:202
TParticle * PopPrimaryForTracking(Int_t iPrim) override
Definition: ShipStack.cxx:158
TParticle * PopNextTrack(Int_t &iTrack) override
Definition: ShipStack.cxx:134
Int_t fNParticles
Number of primary particles.
Definition: ShipStack.h:197
std::map< Int_t, Bool_t > fStoreMap
Definition: ShipStack.h:184
Int_t fNPrimaries
Index of current track.
Definition: ShipStack.h:196
std::stack< TParticle * > fStack
Definition: ShipStack.h:173
std::map< Int_t, Int_t >::iterator fIndexIter
Definition: ShipStack.h:189
TClonesArray * fParticles
Definition: ShipStack.h:178
void SelectTracks()
Definition: ShipStack.cxx:389
Int_t fCurrentTrack
Definition: ShipStack.h:195
std::vector< ShipMCTrack > * fTracks
Definition: ShipStack.h:181
ShipStack(Int_t size=100)
Definition: ShipStack.cxx:32
void AddParticle(TParticle *part)
Definition: ShipStack.cxx:193