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
67 fUseOnlyPrimary = o.fUseOnlyPrimary;
68 fMaxConsequtiveStrips = o.fMaxConsequtiveStrips;
71 fBinFlow = o.fBinFlow;
72 fEtaBinFlow = o.fEtaBinFlow;
73 fPhiBinFlow = o.fPhiBinFlow;
78 //____________________________________________________________________
80 AliFMDMCTrackDensity::DefineOutput(TList* l)
82 fNr = new TH1D("clusterRefs", "# track references per cluster",
84 fNr->SetXTitle("# of track references/cluster");
88 fNt = new TH1D("clusterSize", "cluster length in strips", 21, -.5, 20.5);
89 fNt->SetXTitle("Cluster size [strips]");
93 fBinFlow = new TH2D("binFlow", "#eta and #varphi bin flow",
94 200, -5, 5, 40, -180, 180);
95 fBinFlow->SetXTitle("#Delta#eta");
96 fBinFlow->SetYTitle("#Delta#varphi");
97 fBinFlow->SetDirectory(0);
100 fEtaBinFlow = new TH2D("binFlowEta", "#eta bin flow vs #eta",
101 200, -4, 6, 200, -5, 5);
102 fEtaBinFlow->SetXTitle("#eta of strip");
103 fEtaBinFlow->SetYTitle("#Delta#eta");
104 fEtaBinFlow->SetDirectory(0);
107 fPhiBinFlow = new TH2D("binFlowPhi", "#phi bin flow vs #phi",
108 40, 0, 360, 40, -180, 180);
109 fPhiBinFlow->SetXTitle("#varphi of strip");
110 fPhiBinFlow->SetYTitle("#Delta#varphi");
111 fPhiBinFlow->SetDirectory(0);
115 //____________________________________________________________________
117 AliFMDMCTrackDensity::StoreParticle(AliMCParticle* particle,
118 const AliMCParticle* mother,
123 AliESDFMD& output) const
126 if (longest < 0) return;
128 AliTrackReference* ref = particle->GetTrackReference(longest);
131 // Get the detector coordinates
134 AliFMDStripIndex::Unpack(ref->UserId(), d, r, s, t);
136 // Check if we have value already
137 Double_t old = output.Multiplicity(d,r,s,t);
139 // If invalid, force it valid
140 if (old == AliESDFMD::kInvalidMult) old = 0;
143 output.SetMultiplicity(d,r,s,t,old+1);
145 // Get track-reference stuff
146 Double_t x = ref->X();
147 Double_t y = ref->Y();
148 Double_t z = ref->Z()-vz;
149 Double_t rr = TMath::Sqrt(x*x+y*y);
150 Double_t thetaR = TMath::ATan2(rr,z);
151 Double_t phiR = TMath::ATan2(y,x);
152 Double_t etaR = -TMath::Log(TMath::Tan(thetaR/2));
154 // Correct angle and convert to degrees
155 if (thetaR < 0) thetaR += 2*TMath::Pi();
156 thetaR *= 180. / TMath::Pi();
157 if (phiR < 0) phiR += 2*TMath::Pi();
158 phiR *= 180. / TMath::Pi();
164 const AliMCParticle* mp = (mother ? mother : particle);
165 Double_t dEta = mp->Eta() - etaR;
166 Double_t dPhi = mp->Phi() * 180 / TMath::Pi() - phiR;
167 if (dPhi > 180) dPhi -= 360;
168 if (dPhi < -180) dPhi += 360;
169 fBinFlow->Fill(dEta, dPhi);
170 fEtaBinFlow->Fill(etaR, dEta);
171 fPhiBinFlow->Fill(phiR, dPhi);
174 Info("StoreParticle", "Store @ FMD%d%c[%2d,%3d] nStrips=%3d, "
175 "dEta=%7.4f, dPhi=%d",
176 d, r, s, t, nT, dEta, int(dPhi+.5));
179 //____________________________________________________________________
181 AliFMDMCTrackDensity::GetTrackRefTheta(const AliTrackReference* ref,
184 // Get the incidient angle of the track reference.
185 Double_t x = ref->X();
186 Double_t y = ref->Y();
187 Double_t z = ref->Z()-vz;
188 Double_t rr = TMath::Sqrt(x*x+y*y);
189 Double_t theta= TMath::ATan2(rr,z);
190 Double_t ang = TMath::Abs(TMath::Pi()-theta);
194 //____________________________________________________________________
196 AliFMDMCTrackDensity::GetMother(Int_t iTr,
197 const AliMCEvent& event) const
200 // Track down primary mother
204 const AliMCParticle* p = static_cast<AliMCParticle*>(event.GetTrack(i));
205 if (const_cast<AliMCEvent&>(event).Stack()->IsPhysicalPrimary(i)) return p;
213 //____________________________________________________________________
215 AliFMDMCTrackDensity::Calculate(const AliESDFMD& input,
216 const AliMCEvent& event,
222 // Filter the input kinematics and track references, using
223 // some of the ESD information
226 // input Input ESD event
227 // event Input MC event
228 // vz Vertex position
229 // output Output ESD-like object
230 // primary Per-event histogram of primaries
233 // True on succes, false otherwise
237 // Copy eta values to output
238 for (UShort_t ed = 1; ed <= 3; ed++) {
239 UShort_t nq = (ed == 1 ? 1 : 2);
240 for (UShort_t eq = 0; eq < nq; eq++) {
241 Char_t er = (eq == 0 ? 'I' : 'O');
242 UShort_t ns = (eq == 0 ? 20 : 40);
243 UShort_t nt = (eq == 0 ? 512 : 256);
244 for (UShort_t es = 0; es < ns; es++)
245 for (UShort_t et = 0; et < nt; et++)
246 output.SetEta(ed, er, es, et, input.Eta(ed, er, es, et));
249 AliStack* stack = const_cast<AliMCEvent&>(event).Stack();
250 Int_t nTracks = stack->GetNtrack();//event.GetNumberOfTracks();
251 Int_t nPrim = stack->GetNprimary();//event.GetNumberOfPrimary();
252 for (Int_t iTr = 0; iTr < nTracks; iTr++) {
253 AliMCParticle* particle =
254 static_cast<AliMCParticle*>(event.GetTrack(iTr));
256 // Check the returned particle
257 if (!particle) continue;
259 // Check if this charged and a primary
260 Bool_t isCharged = particle->Charge() != 0;
261 if (!isCharged) continue;
262 Bool_t isPrimary = stack->IsPhysicalPrimary(iTr);
264 // Pseudo rapidity and azimuthal angle
265 Double_t eta = particle->Eta();
266 Double_t phi = particle->Phi();
268 // Fill 'dn/deta' histogram
269 if (isPrimary && iTr < nPrim) {
270 if (primary) primary->Fill(eta, phi);
273 // Bail out if we're only processing primaries - perhaps we should
274 // track back to the original primary?
275 if (fUseOnlyPrimary && !isPrimary) continue;
277 Int_t nTrRef = particle->GetNumberOfTrackReferences();
280 UShort_t oD = 0, oS = 1024, oT = 1024, ooT=1024;
284 // Double_t oTheta= 0;
285 for (Int_t iTrRef = 0; iTrRef < nTrRef; iTrRef++) {
286 AliTrackReference* ref = particle->GetTrackReference(iTrRef);
291 // Check that we hit an FMD element
292 if (ref->DetectorId() != AliTrackReference::kFMD)
295 // Get the detector coordinates
298 AliFMDStripIndex::Unpack(ref->UserId(), d, r, s, t);
300 // Calculate length of last and second to last strips.
302 // IF base of cluster not set, set it here.
303 if (ooT == 1024) ooT = t;
305 // Calculate distance of previous reference to base of cluster
306 nT = TMath::Abs(t - ooT) + 1;
308 // Count number of track refs in this sector
312 // If this is a new detector/ring, then reset the other one
313 // Check if we have a valid old detectorm ring, and sector
314 if (oD > 0 && oR != '\0' && oS != 1024) {
315 // New detector, new ring, or new sector
316 if (d != oD || r != oR || s != oS) {
317 if (fDebug) Info("Process", "New because new sector");
321 if (nT > fMaxConsequtiveStrips) {
322 if (fDebug) Info("Process", "New because too long: %d (%d,%d,%d)",
328 Info("Process", "I=%3d L=%3d D=%d (was %d), R=%c (was %c), "
329 "S=%2d (was %2d) t=%3d (was %3d) nT=%3d/%4d",
330 iTr, longest, d, oD, r, oR, s, oS, t, oT, nT,
331 fMaxConsequtiveStrips);
332 Int_t nnT = TMath::Abs(oT - ooT) + 1;
333 const AliMCParticle* mother = GetMother(iTr, event);
334 StoreParticle(particle, mother, longest, vz, nC, nnT, output);
337 nC = 1; // Reset track-ref counter - we have this->1
338 nT = 0; // Reset cluster size
339 oD = 0; // Reset detector
340 oR = '\0'; // Reset ring
341 oS = 1024; // Reset sector
342 oT = 1024; // Reset old strip
343 ooT = t; // Reset base
347 Info("Process", "New cluster starting at FMD%d%c[%2d,%3d]",
350 Info("Process", "Adding to cluster starting at FMD%d%c[%2d,%3d], "
351 "length=%3d (now in %3d, previous %3d)",
352 d, r, s, ooT, nT, t, oT);
359 nT = TMath::Abs(t-ooT)+1;
361 // The longest passage is determined through the angle
362 Double_t ang = GetTrackRefTheta(ref, vz);
368 } // Loop over track references
369 if (longest < 0) continue; // Nothing found
371 // Get the reference corresponding to the longest path through the detector
373 Info("Process", "I=%3d L=%3d nT=%3d (out of %3d)",
374 iTr, longest, nT, fMaxConsequtiveStrips);
375 const AliMCParticle* mother = GetMother(iTr, event);
376 StoreParticle(particle, mother, longest, vz, nC, nT, output);
377 } // Loop over tracks
380 //____________________________________________________________________
382 AliFMDMCTrackDensity::Print(Option_t* /*option*/) const
384 char ind[gROOT->GetDirLevel()+1];
385 for (Int_t i = 0; i < gROOT->GetDirLevel(); i++) ind[i] = ' ';
386 ind[gROOT->GetDirLevel()] = '\0';
387 std::cout << ind << ClassName() << ": " << GetName() << '\n'
389 << ind << " Only primary tracks: " << fUseOnlyPrimary << '\n'
390 << ind << " Max cluster size: " << fMaxConsequtiveStrips
391 << std::noboolalpha << std::endl;
395 //____________________________________________________________________