1 /**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
6 * Artur Szostak <artursz@iafrica.com> *
8 * Permission to use, copy, modify and distribute this software and its *
9 * documentation strictly for non-commercial purposes is hereby granted *
10 * without fee, provided that the above copyright notice appears in all *
11 * copies and that both the copyright notice and this permission notice *
12 * appear in the supporting documentation. The authors make no claims *
13 * about the suitability of this software for any purpose. It is *
14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
17 // Simple macro to generate N-tuple for performance analysis.
18 // This macro must be compiled and run like so from within the aliroot command
20 // root [0] gSystem->Load("libAliHLTMUON.so");
21 // root [0] .x MakeHitsTable.C+
26 #include "TParticle.h"
28 #include "TStopwatch.h"
33 #include "AliLoader.h"
34 #include "AliRunLoader.h"
38 #include "AliMUONMCDataInterface.h"
39 #include "AliMUONHit.h"
40 #include "AliHLTMUONRootifierComponent.h"
41 #include "AliHLTMUONMansoTrack.h"
51 void MakeTriggerTable(
54 const char* L0outputfile = "output.root",
55 Float_t maxSigma = 4., // 4 standard deviations
56 Float_t sigmaXtrg = 0.5, // 5 mm resolution
57 Float_t sigmaYtrg = 0.5, // 5 mm resolution
58 Float_t sigmaZtrg = 0.02 // 2 microns resolution
61 gSystem->Load("libAliHLTMUON.so");
62 // Must pree load libAliHLTMUON.so before loading this macro and running it in compiled mode.
64 TString fieldnames = "event:isprimary:pdgcode:sign:px:py:pz";
65 for (Int_t i = 11; i <= 14; i++)
74 fieldnames += ":L0sign:L0px:L0py:L0pz:L0fit";
75 for (Int_t i = 11; i <= 14; i++)
84 TNtuple* table = new TNtuple("triggertable", "Table of triggers.", fieldnames);
86 TFile L0file(L0outputfile, "READ");
88 AliMUONMCDataInterface data;
91 Int_t nEvents = data.NumberOfEvents();
92 if (lastEvent < 0) lastEvent = nEvents-1;
93 for (Int_t event = firstEvent; event <= lastEvent; event++)
95 cout << "Processing event: " << event;
99 sprintf(str, "AliHLTMUONEvent;%d", event+1);
100 AliHLTMUONEvent* L0event = dynamic_cast<AliHLTMUONEvent*>( L0file.Get(str) );
104 cerr << "ERROR: Could not find " << str << " in " << L0outputfile << endl;
108 data.GetEvent(event);
110 stack = data.Stack(event);
114 cerr << "ERROR: Stack is NULL" << endl;
118 Int_t trackcount = data.NumberOfParticles();
119 cout << "\ttrackcount = " << trackcount << endl;
121 TArrayF isPrimary(trackcount);
122 TArrayF pdgcode(trackcount);
123 TArrayF sign(trackcount);
124 TArrayF px(trackcount);
125 TArrayF py(trackcount);
126 TArrayF pz(trackcount);
127 TArrayF L0sign(trackcount);
128 TArrayF L0px(trackcount);
129 TArrayF L0py(trackcount);
130 TArrayF L0pz(trackcount);
131 TArrayF L0fit(trackcount);
133 //cout << "Fill particle data" << endl;
134 for (Int_t i = 0; i < trackcount; i++)
136 TParticle* p = data.Particle(i);
137 isPrimary[i] = stack->IsPhysicalPrimary(i) ? 1 : 0;
138 pdgcode[i] = p->GetPdgCode();
139 if (p->GetPDG() != NULL)
141 Double_t charge = p->GetPDG()->Charge();
152 cerr << "ERROR: Could not get the PDG information." << endl;
170 for (Int_t i = 0; i < 4; i++)
172 hitX[i].Set(trackcount);
173 hitY[i].Set(trackcount);
174 hitZ[i].Set(trackcount);
175 L0hitX[i].Set(trackcount);
176 L0hitY[i].Set(trackcount);
177 L0hitZ[i].Set(trackcount);
178 for (Int_t j = 0; j < trackcount; j++)
189 //cout << "Fill hits" << endl;
190 for (Int_t i = 0; i < data.NumberOfTracks(); i++)
191 for (Int_t j = 0; j < data.NumberOfHits(i); j++)
193 AliMUONHit* hit = data.Hit(i, j);
194 Int_t chamber = hit->Chamber() - 1;
195 if (chamber < 0 || chamber >= 14)
197 cerr << "ERROR: Chamber number " << chamber << " is out of range." << endl;
201 //cout << "hit->Track() = " << hit->Track() << endl;
202 if (hit->Track() < 0 || hit->Track() >= trackcount)
204 cerr << "ERROR: Track number " << hit->Track() << " is out of range. [0.."
205 << trackcount << ")" << endl;
208 Int_t particleindex = hit->Track();
212 hitX[chamber-10][particleindex] = hit->X();
213 hitY[chamber-10][particleindex] = hit->Y();
214 hitZ[chamber-10][particleindex] = hit->Z();
218 // Ok now go through the L0 information for this event and correlate
219 // the L0 trigger records to the kine data.
220 // This is done as follows: take a trigger record. Then for each kine track
221 // calculate the distance between each hit of the kine track and corresponding
222 // L0 trigger track fragment hit.
223 // Then sum up the distances and divide by the number of hits matched.
224 // This gives us a fit quality /Chi2 type parameter. The kine track that
225 // has the smallest sum of differences is then chosen as the kine track
226 // correlating to the current L0 trigger record being processed.
227 for (Int_t i = 0; i < L0event->Array().GetEntriesFast(); i++)
229 if (L0event->Array().At(i)->IsA() != AliHLTMUONTriggerRecord::Class())
231 AliHLTMUONTriggerRecord* trigrec = static_cast<AliHLTMUONTriggerRecord*>(L0event->Array().At(i));
233 // Find the best fitting kine track.
234 Double_t bestFitQuality = 1e30;
235 Int_t bestFitTrack = -1;
236 for (Int_t kinetrack = 0; kinetrack < trackcount; kinetrack++)
238 Double_t sumOfDiffs = 0;
239 Double_t hitsMatched = 0;
240 for (Int_t j = 11; j <= 14; j++)
242 const TVector3& hit = trigrec->Hit(j);
243 if (hit == TVector3(0,0,0)) continue;
244 TVector3 hV(hitX[j-11][kinetrack], hitY[j-11][kinetrack], hitZ[j-11][kinetrack]);
245 if (hV == TVector3(0,0,0)) continue;
246 TVector3 diff = hV - hit;
247 Double_t diffX = diff.X() / sigmaXtrg;
248 Double_t diffY = diff.Y() / sigmaYtrg;
249 Double_t diffZ = diff.Z() / sigmaZtrg;
250 if (diffX > maxSigma) continue;
251 if (diffY > maxSigma) continue;
252 if (diffZ > maxSigma) continue;
253 sumOfDiffs += diffX*diffX + diffY*diffY + diffZ*diffZ;
257 // Now check the fit quality.
258 if (hitsMatched <= 0) continue;
259 Double_t fitQuality = sumOfDiffs / hitsMatched;
260 if (fitQuality < bestFitQuality)
262 bestFitQuality = fitQuality;
263 bestFitTrack = kinetrack;
267 if (bestFitTrack < 0)
269 // No track was matched so we need to add a fake track record.
270 Float_t args[7+4*3+5+4*3];
278 for (Int_t j = 0; j < 4; j++)
284 args[7+4*3+0] = trigrec->Sign();
285 args[7+4*3+1] = trigrec->Px();
286 args[7+4*3+2] = trigrec->Py();
287 args[7+4*3+3] = trigrec->Pz();
289 for (Int_t j = 0; j < 4; j++)
291 const TVector3& hit = trigrec->Hit(j+11);
292 args[7+4*3+5+j*3+0] = hit.X();
293 args[7+4*3+5+j*3+1] = hit.Y();
294 args[7+4*3+5+j*3+2] = hit.Z();
300 // Fill the details about the L0 track to the best fitting track info.
301 L0sign[bestFitTrack] = trigrec->Sign();
302 L0px[bestFitTrack] = trigrec->Px();
303 L0py[bestFitTrack] = trigrec->Py();
304 L0pz[bestFitTrack] = trigrec->Pz();
305 L0fit[bestFitTrack] = bestFitQuality;
306 for (Int_t j = 11; j <= 14; j++)
308 const TVector3& hit = trigrec->Hit(j);
309 if (hit == TVector3(0,0,0)) continue;
310 L0hitX[j-11][bestFitTrack] = hit.X();
311 L0hitY[j-11][bestFitTrack] = hit.Y();
312 L0hitZ[j-11][bestFitTrack] = hit.Z();
317 //cout << "Fill table" << endl;
318 for (Int_t i = 0; i < trackcount; i++)
320 Float_t args[7+4*3+5+4*3];
322 args[1] = isPrimary[i];
323 args[2] = pdgcode[i];
328 for (Int_t j = 0; j < 4; j++)
330 args[7+j*3+0] = hitX[j][i];
331 args[7+j*3+1] = hitY[j][i];
332 args[7+j*3+2] = hitZ[j][i];
334 args[7+4*3+0] = L0sign[i];
335 args[7+4*3+1] = L0px[i];
336 args[7+4*3+2] = L0py[i];
337 args[7+4*3+3] = L0pz[i];
338 args[7+4*3+4] = L0fit[i];
339 for (Int_t j = 0; j < 4; j++)
341 args[7+4*3+5+j*3+0] = L0hitX[j][i];
342 args[7+4*3+5+j*3+1] = L0hitY[j][i];
343 args[7+4*3+5+j*3+2] = L0hitZ[j][i];
350 TFile file("triggertable.root", "RECREATE");
352 table->Write(table->GetName(), TObject::kOverwrite);
354 cout << "Done." << endl;