1 #include "AliFMDMCTrackDensity.h"
3 #include <AliMCEvent.h>
4 #include <AliTrackReference.h>
7 #include "AliFMDStripIndex.h"
8 #include "AliFMDFloatMap.h"
16 //____________________________________________________________________
17 AliFMDMCTrackDensity::AliFMDMCTrackDensity()
19 fUseOnlyPrimary(false),
20 fMaxConsequtiveStrips(3),
28 // Default constructor
31 //____________________________________________________________________
32 AliFMDMCTrackDensity::AliFMDMCTrackDensity(const char*)
33 : TNamed("fmdMCTrackDensity","fmdMCTrackDensity"),
34 fUseOnlyPrimary(false),
35 fMaxConsequtiveStrips(3),
43 // Normal constructor constructor
46 //____________________________________________________________________
47 AliFMDMCTrackDensity::AliFMDMCTrackDensity(const AliFMDMCTrackDensity& o)
49 fUseOnlyPrimary(o.fUseOnlyPrimary),
50 fMaxConsequtiveStrips(o.fMaxConsequtiveStrips),
54 fEtaBinFlow(o.fEtaBinFlow),
55 fPhiBinFlow(o.fPhiBinFlow),
58 // Normal constructor constructor
61 //____________________________________________________________________
63 AliFMDMCTrackDensity::operator=(const AliFMDMCTrackDensity& o)
65 // Assignment operator
66 if (&o == this) return *this;
68 fUseOnlyPrimary = o.fUseOnlyPrimary;
69 fMaxConsequtiveStrips = o.fMaxConsequtiveStrips;
72 fBinFlow = o.fBinFlow;
73 fEtaBinFlow = o.fEtaBinFlow;
74 fPhiBinFlow = o.fPhiBinFlow;
79 //____________________________________________________________________
81 AliFMDMCTrackDensity::DefineOutput(TList* l)
83 fNr = new TH1D("clusterRefs", "# track references per cluster",
85 fNr->SetXTitle("# of track references/cluster");
89 fNt = new TH1D("clusterSize", "cluster length in strips", 21, -.5, 20.5);
90 fNt->SetXTitle("Cluster size [strips]");
94 fBinFlow = new TH2D("binFlow", "#eta and #varphi bin flow",
95 200, -5, 5, 40, -180, 180);
96 fBinFlow->SetXTitle("#Delta#eta");
97 fBinFlow->SetYTitle("#Delta#varphi");
98 fBinFlow->SetDirectory(0);
101 fEtaBinFlow = new TH2D("binFlowEta", "#eta bin flow vs #eta",
102 200, -4, 6, 200, -5, 5);
103 fEtaBinFlow->SetXTitle("#eta of strip");
104 fEtaBinFlow->SetYTitle("#Delta#eta");
105 fEtaBinFlow->SetDirectory(0);
108 fPhiBinFlow = new TH2D("binFlowPhi", "#phi bin flow vs #phi",
109 40, 0, 360, 40, -180, 180);
110 fPhiBinFlow->SetXTitle("#varphi of strip");
111 fPhiBinFlow->SetYTitle("#Delta#varphi");
112 fPhiBinFlow->SetDirectory(0);
116 //____________________________________________________________________
118 AliFMDMCTrackDensity::StoreParticle(AliMCParticle* particle,
119 const AliMCParticle* mother,
124 AliESDFMD& output) const
127 if (longest < 0) return;
129 AliTrackReference* ref = particle->GetTrackReference(longest);
132 // Get the detector coordinates
135 AliFMDStripIndex::Unpack(ref->UserId(), d, r, s, t);
137 // Check if we have value already
138 Double_t old = output.Multiplicity(d,r,s,t);
140 // If invalid, force it valid
141 if (old == AliESDFMD::kInvalidMult) old = 0;
144 output.SetMultiplicity(d,r,s,t,old+1);
146 // Get track-reference stuff
147 Double_t x = ref->X();
148 Double_t y = ref->Y();
149 Double_t z = ref->Z()-vz;
150 Double_t rr = TMath::Sqrt(x*x+y*y);
151 Double_t thetaR = TMath::ATan2(rr,z);
152 Double_t phiR = TMath::ATan2(y,x);
153 Double_t etaR = -TMath::Log(TMath::Tan(thetaR/2));
155 // Correct angle and convert to degrees
156 if (thetaR < 0) thetaR += 2*TMath::Pi();
157 thetaR *= 180. / TMath::Pi();
158 if (phiR < 0) phiR += 2*TMath::Pi();
159 phiR *= 180. / TMath::Pi();
165 const AliMCParticle* mp = (mother ? mother : particle);
166 Double_t dEta = mp->Eta() - etaR;
167 Double_t dPhi = mp->Phi() * 180 / TMath::Pi() - phiR;
168 if (dPhi > 180) dPhi -= 360;
169 if (dPhi < -180) dPhi += 360;
170 fBinFlow->Fill(dEta, dPhi);
171 fEtaBinFlow->Fill(etaR, dEta);
172 fPhiBinFlow->Fill(phiR, dPhi);
175 Info("StoreParticle", "Store @ FMD%d%c[%2d,%3d] nStrips=%3d, "
176 "dEta=%7.4f, dPhi=%d",
177 d, r, s, t, nT, dEta, int(dPhi+.5));
180 //____________________________________________________________________
182 AliFMDMCTrackDensity::GetTrackRefTheta(const AliTrackReference* ref,
185 // Get the incidient angle of the track reference.
186 Double_t x = ref->X();
187 Double_t y = ref->Y();
188 Double_t z = ref->Z()-vz;
189 Double_t rr = TMath::Sqrt(x*x+y*y);
190 Double_t theta= TMath::ATan2(rr,z);
191 Double_t ang = TMath::Abs(TMath::Pi()-theta);
195 //____________________________________________________________________
197 AliFMDMCTrackDensity::GetMother(Int_t iTr,
198 const AliMCEvent& event) const
201 // Track down primary mother
205 const AliMCParticle* p = static_cast<AliMCParticle*>(event.GetTrack(i));
206 if (const_cast<AliMCEvent&>(event).Stack()->IsPhysicalPrimary(i)) return p;
214 //____________________________________________________________________
216 AliFMDMCTrackDensity::Calculate(const AliESDFMD& input,
217 const AliMCEvent& event,
223 // Filter the input kinematics and track references, using
224 // some of the ESD information
227 // input Input ESD event
228 // event Input MC event
229 // vz Vertex position
230 // output Output ESD-like object
231 // primary Per-event histogram of primaries
234 // True on succes, false otherwise
238 // Copy eta values to output
239 for (UShort_t ed = 1; ed <= 3; ed++) {
240 UShort_t nq = (ed == 1 ? 1 : 2);
241 for (UShort_t eq = 0; eq < nq; eq++) {
242 Char_t er = (eq == 0 ? 'I' : 'O');
243 UShort_t ns = (eq == 0 ? 20 : 40);
244 UShort_t nt = (eq == 0 ? 512 : 256);
245 for (UShort_t es = 0; es < ns; es++)
246 for (UShort_t et = 0; et < nt; et++)
247 output.SetEta(ed, er, es, et, input.Eta(ed, er, es, et));
250 AliStack* stack = const_cast<AliMCEvent&>(event).Stack();
251 Int_t nTracks = stack->GetNtrack();//event.GetNumberOfTracks();
252 Int_t nPrim = stack->GetNprimary();//event.GetNumberOfPrimary();
253 for (Int_t iTr = 0; iTr < nTracks; iTr++) {
254 AliMCParticle* particle =
255 static_cast<AliMCParticle*>(event.GetTrack(iTr));
257 // Check the returned particle
258 if (!particle) continue;
260 // Check if this charged and a primary
261 Bool_t isCharged = particle->Charge() != 0;
262 if (!isCharged) continue;
263 Bool_t isPrimary = stack->IsPhysicalPrimary(iTr);
265 // Pseudo rapidity and azimuthal angle
266 Double_t eta = particle->Eta();
267 Double_t phi = particle->Phi();
269 // Fill 'dn/deta' histogram
270 if (isPrimary && iTr < nPrim) {
271 if (primary) primary->Fill(eta, phi);
274 // Bail out if we're only processing primaries - perhaps we should
275 // track back to the original primary?
276 if (fUseOnlyPrimary && !isPrimary) continue;
278 Int_t nTrRef = particle->GetNumberOfTrackReferences();
281 UShort_t oD = 0, oS = 1024, oT = 1024, ooT=1024;
285 // Double_t oTheta= 0;
286 for (Int_t iTrRef = 0; iTrRef < nTrRef; iTrRef++) {
287 AliTrackReference* ref = particle->GetTrackReference(iTrRef);
292 // Check that we hit an FMD element
293 if (ref->DetectorId() != AliTrackReference::kFMD)
296 // Get the detector coordinates
299 AliFMDStripIndex::Unpack(ref->UserId(), d, r, s, t);
301 // Calculate length of last and second to last strips.
303 // IF base of cluster not set, set it here.
304 if (ooT == 1024) ooT = t;
306 // Calculate distance of previous reference to base of cluster
307 nT = TMath::Abs(t - ooT) + 1;
309 // Count number of track refs in this sector
313 // If this is a new detector/ring, then reset the other one
314 // Check if we have a valid old detectorm ring, and sector
315 if (oD > 0 && oR != '\0' && oS != 1024) {
316 // New detector, new ring, or new sector
317 if (d != oD || r != oR || s != oS) {
318 if (fDebug) Info("Process", "New because new sector");
322 if (nT > fMaxConsequtiveStrips) {
323 if (fDebug) Info("Process", "New because too long: %d (%d,%d,%d)",
329 Info("Process", "I=%3d L=%3d D=%d (was %d), R=%c (was %c), "
330 "S=%2d (was %2d) t=%3d (was %3d) nT=%3d/%4d",
331 iTr, longest, d, oD, r, oR, s, oS, t, oT, nT,
332 fMaxConsequtiveStrips);
333 Int_t nnT = TMath::Abs(oT - ooT) + 1;
334 const AliMCParticle* mother = GetMother(iTr, event);
335 StoreParticle(particle, mother, longest, vz, nC, nnT, output);
338 nC = 1; // Reset track-ref counter - we have this->1
339 nT = 0; // Reset cluster size
340 oD = 0; // Reset detector
341 oR = '\0'; // Reset ring
342 oS = 1024; // Reset sector
343 oT = 1024; // Reset old strip
344 ooT = t; // Reset base
348 Info("Process", "New cluster starting at FMD%d%c[%2d,%3d]",
351 Info("Process", "Adding to cluster starting at FMD%d%c[%2d,%3d], "
352 "length=%3d (now in %3d, previous %3d)",
353 d, r, s, ooT, nT, t, oT);
360 nT = TMath::Abs(t-ooT)+1;
362 // The longest passage is determined through the angle
363 Double_t ang = GetTrackRefTheta(ref, vz);
369 } // Loop over track references
370 if (longest < 0) continue; // Nothing found
372 // Get the reference corresponding to the longest path through the detector
374 Info("Process", "I=%3d L=%3d nT=%3d (out of %3d)",
375 iTr, longest, nT, fMaxConsequtiveStrips);
376 const AliMCParticle* mother = GetMother(iTr, event);
377 StoreParticle(particle, mother, longest, vz, nC, nT, output);
378 } // Loop over tracks
381 //____________________________________________________________________
383 AliFMDMCTrackDensity::Print(Option_t* /*option*/) const
385 char ind[gROOT->GetDirLevel()+1];
386 for (Int_t i = 0; i < gROOT->GetDirLevel(); i++) ind[i] = ' ';
387 ind[gROOT->GetDirLevel()] = '\0';
388 std::cout << ind << ClassName() << ": " << GetName() << '\n'
390 << ind << " Only primary tracks: " << fUseOnlyPrimary << '\n'
391 << ind << " Max cluster size: " << fMaxConsequtiveStrips
392 << std::noboolalpha << std::endl;
396 //____________________________________________________________________