]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWG2/RESONANCES/AliRsnMiniAnalysisTask.cxx
Added first version of cut monitoring + style format applied
[u/mrichter/AliRoot.git] / PWG2 / RESONANCES / AliRsnMiniAnalysisTask.cxx
CommitLineData
03d23846 1//
2// Analysis task for 'mini' sub-package
3// Contains all definitions needed for running an analysis:
4// -- global event cut
5// -- a list of track cuts (any number)
6// -- definitions of output histograms
7// -- values to be computed.
8// Each one must be defined using the "CREATE" methods, which
9// add directly a new element in the task collections, and don't
10// need an external object to be passed to the task itself.
11//
12
13#include <Riostream.h>
14
03d23846 15#include <TH1.h>
6aaeb33c 16#include <TList.h>
17#include <TTree.h>
52e6652d 18#include <TStopwatch.h>
03d23846 19
20#include "AliLog.h"
6aaeb33c 21#include "AliEventplane.h"
22#include "AliMultiplicity.h"
23#include "AliTriggerAnalysis.h"
03d23846 24#include "AliAnalysisManager.h"
6aaeb33c 25#include "AliInputEventHandler.h"
26
03d23846 27#include "AliESDtrackCuts.h"
28#include "AliESDUtils.h"
6aaeb33c 29
03d23846 30#include "AliAODEvent.h"
03d23846 31#include "AliAODMCParticle.h"
32
33#include "AliRsnCutSet.h"
6aaeb33c 34#include "AliRsnMiniPair.h"
03d23846 35#include "AliRsnMiniEvent.h"
36#include "AliRsnMiniParticle.h"
03d23846 37
38#include "AliRsnMiniAnalysisTask.h"
39
52e6652d 40
03d23846 41ClassImp(AliRsnMiniAnalysisTask)
42
43//__________________________________________________________________________________________________
44AliRsnMiniAnalysisTask::AliRsnMiniAnalysisTask() :
45 AliAnalysisTaskSE(),
c80938f5 46 fUseMC(kFALSE),
03d23846 47 fEvNum(0),
48 fUseCentrality(kFALSE),
49 fCentralityType("QUALITY"),
caef2e3c 50 fContinuousMix(kTRUE),
03d23846 51 fNMix(0),
52 fMaxDiffMult(10),
53 fMaxDiffVz(1.0),
54 fMaxDiffAngle(1E20),
55 fOutput(0x0),
56 fHistograms("AliRsnMiniOutput", 0),
57 fValues("AliRsnMiniValue", 0),
58 fHEventStat(0x0),
59 fEventCuts(0x0),
60 fTrackCuts(0),
61 fRsnEvent(),
c80938f5 62 fEvBuffer(0x0),
c80938f5 63 fTriggerAna(0x0),
6aaeb33c 64 fESDtrackCuts(0x0),
caef2e3c 65 fMiniEvent(0x0),
61f275d1 66 fBigOutput(kFALSE),
67 fMixPrintRefresh(-1)
03d23846 68{
69//
70// Dummy constructor ALWAYS needed for I/O.
71//
72}
73
74//__________________________________________________________________________________________________
c80938f5 75AliRsnMiniAnalysisTask::AliRsnMiniAnalysisTask(const char *name, Bool_t useMC) :
03d23846 76 AliAnalysisTaskSE(name),
c80938f5 77 fUseMC(useMC),
03d23846 78 fEvNum(0),
79 fUseCentrality(kFALSE),
80 fCentralityType("QUALITY"),
caef2e3c 81 fContinuousMix(kTRUE),
03d23846 82 fNMix(0),
83 fMaxDiffMult(10),
84 fMaxDiffVz(1.0),
85 fMaxDiffAngle(1E20),
86 fOutput(0x0),
87 fHistograms("AliRsnMiniOutput", 0),
88 fValues("AliRsnMiniValue", 0),
89 fHEventStat(0x0),
90 fEventCuts(0x0),
91 fTrackCuts(0),
92 fRsnEvent(),
c80938f5 93 fEvBuffer(0x0),
c80938f5 94 fTriggerAna(0x0),
6aaeb33c 95 fESDtrackCuts(0x0),
caef2e3c 96 fMiniEvent(0x0),
61f275d1 97 fBigOutput(kFALSE),
98 fMixPrintRefresh(-1)
03d23846 99{
100//
101// Default constructor.
102// Define input and output slots here (never in the dummy constructor)
103// Input slot #0 works with a TChain - it is connected to the default input container
104// Output slot #1 writes into a TH1 container
105//
106
107 DefineOutput(1, TList::Class());
108}
109
110//__________________________________________________________________________________________________
52e6652d 111AliRsnMiniAnalysisTask::AliRsnMiniAnalysisTask(const AliRsnMiniAnalysisTask &copy) :
03d23846 112 AliAnalysisTaskSE(copy),
c80938f5 113 fUseMC(copy.fUseMC),
03d23846 114 fEvNum(0),
115 fUseCentrality(copy.fUseCentrality),
116 fCentralityType(copy.fCentralityType),
caef2e3c 117 fContinuousMix(copy.fContinuousMix),
03d23846 118 fNMix(copy.fNMix),
119 fMaxDiffMult(copy.fMaxDiffMult),
120 fMaxDiffVz(copy.fMaxDiffVz),
121 fMaxDiffAngle(copy.fMaxDiffAngle),
122 fOutput(0x0),
123 fHistograms(copy.fHistograms),
124 fValues(copy.fValues),
125 fHEventStat(0x0),
126 fEventCuts(copy.fEventCuts),
127 fTrackCuts(copy.fTrackCuts),
128 fRsnEvent(),
c80938f5 129 fEvBuffer(0x0),
c80938f5 130 fTriggerAna(copy.fTriggerAna),
6aaeb33c 131 fESDtrackCuts(copy.fESDtrackCuts),
caef2e3c 132 fMiniEvent(0x0),
61f275d1 133 fBigOutput(copy.fBigOutput),
134 fMixPrintRefresh(copy.fMixPrintRefresh)
03d23846 135{
136//
137// Copy constructor.
138// Implemented as requested by C++ standards.
139// Can be used in PROOF and by plugins.
140//
141}
142
143//__________________________________________________________________________________________________
52e6652d 144AliRsnMiniAnalysisTask &AliRsnMiniAnalysisTask::operator=(const AliRsnMiniAnalysisTask &copy)
03d23846 145{
146//
147// Assignment operator.
148// Implemented as requested by C++ standards.
149// Can be used in PROOF and by plugins.
150//
151
152 AliAnalysisTaskSE::operator=(copy);
e6f3a909 153 if (this == &copy)
61f275d1 154 return *this;
c80938f5 155 fUseMC = copy.fUseMC;
03d23846 156 fUseCentrality = copy.fUseCentrality;
157 fCentralityType = copy.fCentralityType;
caef2e3c 158 fContinuousMix = copy.fContinuousMix;
03d23846 159 fNMix = copy.fNMix;
160 fMaxDiffMult = copy.fMaxDiffMult;
161 fMaxDiffVz = copy.fMaxDiffVz;
162 fMaxDiffAngle = copy.fMaxDiffAngle;
163 fHistograms = copy.fHistograms;
164 fValues = copy.fValues;
165 fEventCuts = copy.fEventCuts;
166 fTrackCuts = copy.fTrackCuts;
167 fTriggerAna = copy.fTriggerAna;
c80938f5 168 fESDtrackCuts = copy.fESDtrackCuts;
caef2e3c 169 fBigOutput = copy.fBigOutput;
61f275d1 170 fMixPrintRefresh = copy.fMixPrintRefresh;
03d23846 171 return (*this);
172}
173
174//__________________________________________________________________________________________________
175AliRsnMiniAnalysisTask::~AliRsnMiniAnalysisTask()
176{
177//
52e6652d 178// Destructor.
03d23846 179// Clean-up the output list, but not the histograms that are put inside
180// (the list is owner and will clean-up these histograms). Protect in PROOF case.
181//
182
d573d2fb 183
03d23846 184 if (fOutput && !AliAnalysisManager::GetAnalysisManager()->IsProofMode()) {
185 delete fOutput;
d573d2fb 186 delete fEvBuffer;
03d23846 187 }
188}
189
190//__________________________________________________________________________________________________
191Int_t AliRsnMiniAnalysisTask::AddTrackCuts(AliRsnCutSet *cuts)
192{
193//
194// Add a new cut set for a new criterion for track selection.
195// A user can add as many as he wants, and each one corresponds
196// to one of the available bits in the AliRsnMiniParticle mask.
197// The only check is the following: if a cut set with the same name
198// as the argument is there, this is not added.
199// Return value is the array position of this set.
200//
201
202 TObject *obj = fTrackCuts.FindObject(cuts->GetName());
52e6652d 203
03d23846 204 if (obj) {
205 AliInfo(Form("A cut set named '%s' already exists", cuts->GetName()));
206 return fTrackCuts.IndexOf(obj);
207 } else {
208 fTrackCuts.AddLast(cuts);
209 return fTrackCuts.IndexOf(cuts);
210 }
211}
212
213//__________________________________________________________________________________________________
214void AliRsnMiniAnalysisTask::UserCreateOutputObjects()
215{
216//
217// Initialization of outputs.
218// This is called once per worker node.
219//
220
221 // reset counter
9e7b94f5 222 fEvNum = -1;
52e6652d 223
d573d2fb 224 // message
225 AliInfo(Form("Selected event characterization: %s (%s)", (fUseCentrality ? "centrality" : "multiplicity"), fCentralityType.Data()));
03d23846 226
227 // initialize trigger analysis
c80938f5 228 if (fTriggerAna) delete fTriggerAna;
03d23846 229 fTriggerAna = new AliTriggerAnalysis;
52e6652d 230
c80938f5 231 // initialize ESD quality cuts
232 if (fESDtrackCuts) delete fESDtrackCuts;
233 fESDtrackCuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2010();
03d23846 234
235 // create list and set it as owner of its content (MANDATORY)
caef2e3c 236 if (fBigOutput) OpenFile(1);
03d23846 237 fOutput = new TList();
238 fOutput->SetOwner();
52e6652d 239
03d23846 240 // initialize event statistics counter
241 fHEventStat = new TH1F("hEventStat", "Event statistics", 4, 0.0, 4.0);
242 fHEventStat->GetXaxis()->SetBinLabel(1, "CINT1B");
243 fHEventStat->GetXaxis()->SetBinLabel(2, "V0AND");
244 fHEventStat->GetXaxis()->SetBinLabel(3, "Candle");
245 fHEventStat->GetXaxis()->SetBinLabel(4, "Accepted");
246 fOutput->Add(fHEventStat);
52e6652d 247
61f275d1 248 TIter next(&fTrackCuts);
249 AliRsnCutSet *cs;
250 while ((cs = (AliRsnCutSet *) next())) {
251 cs->Init(fOutput);
252 }
253
03d23846 254 // create temporary tree for filtered events
6aaeb33c 255 if (fMiniEvent) delete fMiniEvent;
c80938f5 256 fEvBuffer = new TTree("EventBuffer", "Temporary buffer for mini events");
6aaeb33c 257 fEvBuffer->Branch("events", "AliRsnMiniEvent", &fMiniEvent);
52e6652d 258
03d23846 259 // create one histogram per each stored definition (event histograms)
260 Int_t i, ndef = fHistograms.GetEntries();
261 AliRsnMiniOutput *def = 0x0;
262 for (i = 0; i < ndef; i++) {
52e6652d 263 def = (AliRsnMiniOutput *)fHistograms[i];
03d23846 264 if (!def) continue;
265 if (!def->Init(GetName(), fOutput)) {
266 AliError(Form("Def '%s': failed initialization", def->GetName()));
267 continue;
268 }
269 }
52e6652d 270
03d23846 271 // post data for ALL output slots >0 here, to get at least an empty histogram
272 PostData(1, fOutput);
273}
274
275//__________________________________________________________________________________________________
276void AliRsnMiniAnalysisTask::UserExec(Option_t *)
277{
278//
6aaeb33c 279// Computation loop.
280// In this case, it checks if the event is acceptable, and eventually
281// creates the corresponding mini-event and stores it in the buffer.
282// The real histogram filling is done at the end, in "FinishTaskOutput".
03d23846 283//
284
9e7b94f5 285 // increment event counter
03d23846 286 fEvNum++;
9e7b94f5 287
03d23846 288 // check current event
289 Char_t check = CheckCurrentEvent();
290 if (!check) return;
52e6652d 291
d573d2fb 292 // setup PID response
52e6652d 293 AliAnalysisManager *man = AliAnalysisManager::GetAnalysisManager();
294 AliInputEventHandler *inputHandler = (AliInputEventHandler *)man->GetInputEventHandler();
295 fRsnEvent.SetPIDResponse(inputHandler->GetPIDResponse());
296
6aaeb33c 297 // fill a mini-event from current
298 // and skip this event if no tracks were accepted
45aa62b9 299 FillMiniEvent(check);
52e6652d 300
6aaeb33c 301 // fill MC based histograms on mothers,
302 // which do need the original event
c80938f5 303 if (fUseMC) {
304 if (fRsnEvent.IsESD() && fMCEvent)
6aaeb33c 305 FillTrueMotherESD(fMiniEvent);
c80938f5 306 else if (fRsnEvent.IsAOD() && fRsnEvent.GetAODList())
6aaeb33c 307 FillTrueMotherAOD(fMiniEvent);
03d23846 308 }
52e6652d 309
9e7b94f5 310 // if the event is not empty, store it
311 if (fMiniEvent->IsEmpty()) {
312 AliDebugClass(2, Form("Rejecting empty event #%d", fEvNum));
313 } else {
314 Int_t id = fEvBuffer->GetEntries();
315 AliDebugClass(2, Form("Adding event #%d with ID = %d", fEvNum, id));
316 fMiniEvent->ID() = id;
317 fEvBuffer->Fill();
318 }
52e6652d 319
6aaeb33c 320 // post data for computed stuff
03d23846 321 PostData(1, fOutput);
322}
323
324//__________________________________________________________________________________________________
325void AliRsnMiniAnalysisTask::FinishTaskOutput()
326{
327//
6aaeb33c 328// This function is called at the end of the loop on available events,
329// and then the buffer will be full with all the corresponding mini-events,
330// each one containing all tracks selected by each of the available track cuts.
331// Here a loop is done on each of these events, and both single-event and mixing are computed
03d23846 332//
333
6aaeb33c 334 // security code: reassign the buffer to the mini-event cursor
335 fEvBuffer->SetBranchAddress("events", &fMiniEvent);
52e6652d 336 TStopwatch timer;
0efb7042 337 // prepare variables
6aaeb33c 338 Int_t ievt, nEvents = (Int_t)fEvBuffer->GetEntries();
339 Int_t idef, nDefs = fHistograms.GetEntries();
45aa62b9 340 Int_t imix, iloop, ifill;
6aaeb33c 341 AliRsnMiniOutput *def = 0x0;
342 AliRsnMiniOutput::EComputation compType;
52e6652d 343
61f275d1 344 Int_t printNum = fMixPrintRefresh;
345 if (printNum < 0) {
346 if (nEvents>1e5) printNum=nEvents/100;
347 else if (nEvents>1e4) printNum=nEvents/10;
348 else printNum = 0;
349 }
350
6aaeb33c 351 // loop on events, and for each one fill all outputs
352 // using the appropriate procedure depending on its type
353 // only mother-related histograms are filled in UserExec,
354 // since they require direct access to MC event
52e6652d 355 timer.Start();
6aaeb33c 356 for (ievt = 0; ievt < nEvents; ievt++) {
357 // get next entry
358 fEvBuffer->GetEntry(ievt);
52e6652d 359 if (printNum&&(ievt%printNum==0)) {
360 AliInfo(Form("[%s] Std.Event %d/%d",GetName(), ievt,nEvents));
61f275d1 361 timer.Stop(); timer.Print(); fflush(stdout); timer.Start(kFALSE);
52e6652d 362 }
45aa62b9 363 // fill
6aaeb33c 364 for (idef = 0; idef < nDefs; idef++) {
52e6652d 365 def = (AliRsnMiniOutput *)fHistograms[idef];
6aaeb33c 366 if (!def) continue;
367 compType = def->GetComputation();
368 // execute computation in the appropriate way
369 switch (compType) {
370 case AliRsnMiniOutput::kEventOnly:
9e7b94f5 371 //AliDebugClass(1, Form("Event %d, def '%s': event-value histogram filling", ievt, def->GetName()));
45aa62b9 372 ifill = 1;
0efb7042 373 def->FillEvent(fMiniEvent, &fValues);
6aaeb33c 374 break;
375 case AliRsnMiniOutput::kTruePair:
9e7b94f5 376 //AliDebugClass(1, Form("Event %d, def '%s': true-pair histogram filling", ievt, def->GetName()));
0efb7042 377 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
6aaeb33c 378 break;
379 case AliRsnMiniOutput::kTrackPair:
9e7b94f5 380 //AliDebugClass(1, Form("Event %d, def '%s': pair-value histogram filling", ievt, def->GetName()));
0efb7042 381 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
6aaeb33c 382 break;
383 case AliRsnMiniOutput::kTrackPairRotated1:
9e7b94f5 384 //AliDebugClass(1, Form("Event %d, def '%s': rotated (1) background histogram filling", ievt, def->GetName()));
0efb7042 385 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
6aaeb33c 386 break;
387 case AliRsnMiniOutput::kTrackPairRotated2:
9e7b94f5 388 //AliDebugClass(1, Form("Event %d, def '%s': rotated (2) background histogram filling", ievt, def->GetName()));
0efb7042 389 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
6aaeb33c 390 break;
391 default:
392 // other kinds are processed elsewhere
45aa62b9 393 ifill = 0;
6aaeb33c 394 AliDebugClass(2, Form("Computation = %d", (Int_t)compType));
395 }
45aa62b9 396 // message
397 AliDebugClass(1, Form("Event %6d: def = '%15s' -- fills = %5d", ievt, def->GetName(), ifill));
03d23846 398 }
399 }
52e6652d 400
0efb7042 401 // if no mixing is required, stop here and post the output
402 if (fNMix < 1) {
403 AliDebugClass(2, "Stopping here, since no mixing is required");
404 PostData(1, fOutput);
405 return;
406 }
52e6652d 407
0efb7042 408 // initialize mixing counter
9e7b94f5 409 Int_t nmatched[nEvents];
410 TString *smatched = new TString[nEvents];
0efb7042 411 for (ievt = 0; ievt < nEvents; ievt++) {
9e7b94f5 412 smatched[ievt] = "|";
413 nmatched[ievt] = 0;
0efb7042 414 }
61f275d1 415
416
52e6652d 417 AliInfo(Form("[%s] Std.Event %d/%d",GetName(), nEvents,nEvents));
61f275d1 418 timer.Stop(); timer.Print(); timer.Start(); fflush(stdout);
52e6652d 419
0efb7042 420 // search for good matchings
421 for (ievt = 0; ievt < nEvents; ievt++) {
52e6652d 422 if (printNum&&(ievt%printNum==0)) {
423 AliInfo(Form("[%s] EventMixing searching %d/%d",GetName(),ievt,nEvents));
424 timer.Stop(); timer.Print(); timer.Start(kFALSE); fflush(stdout);
425 }
9e7b94f5 426 if (nmatched[ievt] >= fNMix) continue;
0efb7042 427 fEvBuffer->GetEntry(ievt);
428 AliRsnMiniEvent evMain(*fMiniEvent);
429 for (iloop = 1; iloop < nEvents; iloop++) {
430 imix = ievt + iloop;
431 if (imix >= nEvents) imix -= nEvents;
432 if (imix == ievt) continue;
433 // text next entry
434 fEvBuffer->GetEntry(imix);
435 // skip if events are not matched
caef2e3c 436 if (!EventsMatch(&evMain, fMiniEvent)) continue;
0efb7042 437 // check that the array of good matches for mixed does not already contain main event
9e7b94f5 438 if (smatched[imix].Contains(Form("|%d|", ievt))) continue;
439 // check that the found good events has not enough matches already
440 if (nmatched[imix] >= fNMix) continue;
0efb7042 441 // add new mixing candidate
9e7b94f5 442 smatched[ievt].Append(Form("%d|", imix));
443 nmatched[ievt]++;
444 nmatched[imix]++;
445 if (nmatched[ievt] >= fNMix) break;
0efb7042 446 }
9e7b94f5 447 AliDebugClass(1, Form("Matches for event %5d = %d [%s] (missing are declared above)", evMain.ID(), nmatched[ievt], smatched[ievt].Data()));
0efb7042 448 }
61f275d1 449
52e6652d 450 AliInfo(Form("[%s] EventMixing searching %d/%d",GetName(),nEvents,nEvents));
61f275d1 451 timer.Stop(); timer.Print(); fflush(stdout); timer.Start();
52e6652d 452
0efb7042 453 // perform mixing
454 TObjArray *list = 0x0;
455 TObjString *os = 0x0;
456 for (ievt = 0; ievt < nEvents; ievt++) {
52e6652d 457 if (printNum&&(ievt%printNum==0)) {
458 AliInfo(Form("[%s] EventMixing %d/%d",GetName(),ievt,nEvents));
459 timer.Stop(); timer.Print(); timer.Start(kFALSE); fflush(stdout);
460 }
0efb7042 461 ifill = 0;
462 fEvBuffer->GetEntry(ievt);
463 AliRsnMiniEvent evMain(*fMiniEvent);
9e7b94f5 464 list = smatched[ievt].Tokenize("|");
0efb7042 465 TObjArrayIter next(list);
52e6652d 466 while ( (os = (TObjString *)next()) ) {
0efb7042 467 imix = os->GetString().Atoi();
0efb7042 468 fEvBuffer->GetEntry(imix);
469 for (idef = 0; idef < nDefs; idef++) {
52e6652d 470 def = (AliRsnMiniOutput *)fHistograms[idef];
0efb7042 471 if (!def) continue;
472 if (!def->IsTrackPairMix()) continue;
d573d2fb 473 ifill += def->FillPair(&evMain, fMiniEvent, &fValues, kTRUE);
9e7b94f5 474 if (!def->IsSymmetric()) {
475 AliDebugClass(2, "Reflecting non symmetric pair");
476 ifill += def->FillPair(fMiniEvent, &evMain, &fValues, kFALSE);
477 }
0efb7042 478 }
479 }
480 delete list;
481 }
52e6652d 482
9e7b94f5 483 delete [] smatched;
52e6652d 484
485 AliInfo(Form("[%s] EventMixing %d/%d",GetName(),nEvents,nEvents));
61f275d1 486 timer.Stop(); timer.Print(); fflush(stdout);
52e6652d 487
0efb7042 488 /*
52e6652d 489 OLD
0efb7042 490 ifill = 0;
491 for (iloop = 1; iloop < nEvents; iloop++) {
492 imix = ievt + iloop;
493 // restart from beginning if reached last event
494 if (imix >= nEvents) imix -= nEvents;
495 // avoid to mix an event with itself
496 if (imix == ievt) continue;
497 // skip all events already mixed enough times
498 if (fNMixed[ievt] >= fNMix) break;
499 if (fNMixed[imix] >= fNMix) continue;
500 fEvBuffer->GetEntry(imix);
501 // skip if events are not matched
502 if (TMath::Abs(evMain.Vz() - fMiniEvent->Vz() ) > fMaxDiffVz ) continue;
503 if (TMath::Abs(evMain.Mult() - fMiniEvent->Mult() ) > fMaxDiffMult ) continue;
504 if (TMath::Abs(evMain.Angle() - fMiniEvent->Angle()) > fMaxDiffAngle) continue;
505 // found a match: increment counter for both events
506 AliDebugClass(1, Form("Event %d, def '%s': event mixing (%d with %d)", ievt, def->GetName(), ievt, imix));
507 fNMixed[ievt]++;
508 fNMixed[imix]++;
509 // process mixing
510 ifill += def->FillPair(&evMain, fMiniEvent, &fValues);
511 // stop if mixed enough times
512 if (fNMixed[ievt] >= fNMix) break;
513 }
52e6652d 514 break;
6aaeb33c 515 // print number of mixings done with each event
45aa62b9 516 for (ievt = 0; ievt < nEvents; ievt++) {
517 AliDebugClass(2, Form("Event %6d: mixed %2d times", ievt, fNMixed[ievt]));
518 }
0efb7042 519 */
52e6652d 520
6aaeb33c 521 // post computed data
03d23846 522 PostData(1, fOutput);
523}
524
525//__________________________________________________________________________________________________
526void AliRsnMiniAnalysisTask::Terminate(Option_t *)
527{
528//
529// Draw result to screen, or perform fitting, normalizations
530// Called once at the end of the query
531//
532
52e6652d 533 fOutput = dynamic_cast<TList *>(GetOutputData(1));
534 if (!fOutput) {
535 AliError("Could not retrieve TList fOutput");
536 return;
03d23846 537 }
538}
539
540//__________________________________________________________________________________________________
541Char_t AliRsnMiniAnalysisTask::CheckCurrentEvent()
542{
543//
c80938f5 544// This method checks if current event is OK for analysis.
545// In case it is, the pointers of the local AliRsnEvent data member
546// will point to it, in order to allow cut checking, otherwise the
547// function exits with a failure message.
548// ---
549// ESD events must pass the physics selection, AOD are supposed to do.
550// ---
551// While checking the event, a histogram is filled to count the number
552// of CINT1B, V0AND and CANDLE events, which are needed for normalization
553// ---
554// Return values can be:
03d23846 555// -- 'E' if the event is accepted and is ESD
556// -- 'A' if the event is accepted and is AOD
557// -- 0 if the event is not accepted
558//
559
560 // string to sum messages
561 TString msg("");
52e6652d 562
03d23846 563 // check input type
c80938f5 564 // exit points are provided in all cases an event is bad
565 // if this block is passed, an event can be rejected only
566 // if it does not pass the set of event cuts defined in the task
03d23846 567 Char_t output = 0;
c80938f5 568 Bool_t isSelected;
569 if (fInputEvent->InheritsFrom(AliESDEvent::Class())) {
570 // type ESD
03d23846 571 output = 'E';
c80938f5 572 // ESD specific check: Physics Selection
573 // --> if this is failed, the event is rejected
52e6652d 574 isSelected = (((AliInputEventHandler *)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))->IsEventSelected() & AliVEvent::kMB);
c80938f5 575 if (!isSelected) {
45aa62b9 576 AliDebugClass(2, "Event does not pass physics selections");
c80938f5 577 fRsnEvent.SetRef(0x0);
578 fRsnEvent.SetRefMC(0x0);
579 return 0;
580 }
581 // set reference to input
582 fRsnEvent.SetRef(fInputEvent);
583 // add MC if requested and available
584 if (fUseMC) {
52e6652d 585 if (fMCEvent)
c80938f5 586 fRsnEvent.SetRefMC(fMCEvent);
587 else {
588 AliWarning("MC event requested but not available");
589 fRsnEvent.SetRefMC(0x0);
590 }
591 }
592 } else if (fInputEvent->InheritsFrom(AliAODEvent::Class())) {
593 // type AOD
03d23846 594 output = 'A';
c80938f5 595 // set reference to input
596 fRsnEvent.SetRef(fInputEvent);
597 // add MC if requested and available (it is in the same object)
598 if (fUseMC) {
599 fRsnEvent.SetRefMC(fInputEvent);
600 if (!fRsnEvent.GetAODList()) {
601 AliWarning("MC event requested but not available");
602 fRsnEvent.SetRefMC(0x0);
603 }
604 }
605 } else {
03d23846 606 AliError(Form("Bad input event class: %s", fInputEvent->ClassName()));
c80938f5 607 // reset pointers in local AliRsnEvent object
608 fRsnEvent.SetRef(0x0);
609 fRsnEvent.SetRefMC(0x0);
03d23846 610 return 0;
611 }
52e6652d 612
c80938f5 613 // fill counter of accepted events
614 fHEventStat->Fill(0.1);
52e6652d 615
03d23846 616 // check if it is V0AND
c80938f5 617 // --> uses a cast to AliESDEvent even if the input is an AliAODEvent
52e6652d 618 Bool_t v0A = fTriggerAna->IsOfflineTriggerFired((AliESDEvent *)fInputEvent, AliTriggerAnalysis::kV0A);
619 Bool_t v0C = fTriggerAna->IsOfflineTriggerFired((AliESDEvent *)fInputEvent, AliTriggerAnalysis::kV0C);
03d23846 620 if (v0A && v0C) {
621 msg += " -- VOAND = YES";
622 fHEventStat->Fill(1.1);
623 } else {
624 msg += " -- VOAND = NO ";
625 }
52e6652d 626
03d23846 627 // check candle
c80938f5 628 // --> requires at least one good quality track with Pt > 0.5 and |eta| <= 0.8
629 Int_t iTrack, ntracksLoop = fInputEvent->GetNumberOfTracks();
03d23846 630 Bool_t candle = kFALSE;
52e6652d 631 for (iTrack = 0; iTrack < ntracksLoop; iTrack++) {
632 AliVTrack *track = (AliVTrack *)fInputEvent->GetTrack(iTrack);
633 AliESDtrack *esdt = dynamic_cast<AliESDtrack *>(track);
634 AliAODTrack *aodt = dynamic_cast<AliAODTrack *>(track);
03d23846 635 if (track->Pt() < 0.5) continue;
636 if(TMath::Abs(track->Eta()) > 0.8) continue;
c80938f5 637 if (esdt) if (!fESDtrackCuts->AcceptTrack(esdt)) continue;
638 if (aodt) if (!aodt->TestFilterBit(5)) continue;
03d23846 639 candle = kTRUE;
640 break;
641 }
642 if (candle) {
52e6652d 643 msg += " -- CANDLE = YES";
03d23846 644 fHEventStat->Fill(2.1);
645 } else {
52e6652d 646 msg += " -- CANDLE = NO ";
03d23846 647 }
52e6652d 648
c80938f5 649 // if event cuts are defined, they are checked here
650 // final decision on the event depends on this
651 isSelected = kTRUE;
03d23846 652 if (fEventCuts) {
653 if (!fEventCuts->IsSelected(&fRsnEvent)) {
654 msg += " -- Local cuts = REJECTED";
c80938f5 655 isSelected = kFALSE;
03d23846 656 } else {
657 msg += " -- Local cuts = ACCEPTED";
c80938f5 658 isSelected = kTRUE;
03d23846 659 }
660 } else {
661 msg += " -- Local cuts = NONE";
c80938f5 662 isSelected = kTRUE;
03d23846 663 }
52e6652d 664
03d23846 665 // if the above exit point is not taken, the event is accepted
9e7b94f5 666 AliDebugClass(2, Form("Stats: %s", msg.Data()));
c80938f5 667 if (isSelected) {
668 fHEventStat->Fill(3.1);
669 return output;
670 } else {
671 return 0;
672 }
03d23846 673}
674
6aaeb33c 675//__________________________________________________________________________________________________
45aa62b9 676void AliRsnMiniAnalysisTask::FillMiniEvent(Char_t evType)
6aaeb33c 677{
678//
679// Refresh cursor mini-event data member to fill with current event.
680// Returns the total number of tracks selected.
681//
682
683 // assign event-related values
45aa62b9 684 if (fMiniEvent) delete fMiniEvent;
6aaeb33c 685 fMiniEvent = new AliRsnMiniEvent;
686 fMiniEvent->Vz() = fInputEvent->GetPrimaryVertex()->GetZ();
687 fMiniEvent->Angle() = ComputeAngle();
688 fMiniEvent->Mult() = ComputeCentrality((evType == 'E'));
45aa62b9 689 AliDebugClass(2, Form("Event %d: type = %c -- vz = %f -- mult = %f -- angle = %f", fEvNum, evType, fMiniEvent->Vz(), fMiniEvent->Mult(), fMiniEvent->Angle()));
52e6652d 690
6aaeb33c 691 // loop on daughters and assign track-related values
692 Int_t ic, ncuts = fTrackCuts.GetEntries();
693 Int_t ip, npart = fRsnEvent.GetAbsoluteSum();
45aa62b9 694 Int_t npos = 0, nneg = 0, nneu = 0;
6aaeb33c 695 AliRsnDaughter cursor;
696 AliRsnMiniParticle miniParticle;
697 for (ip = 0; ip < npart; ip++) {
698 // point cursor to next particle
699 fRsnEvent.SetDaughter(cursor, ip);
700 // copy momentum and MC info if present
701 miniParticle.CopyDaughter(&cursor);
45aa62b9 702 miniParticle.Index() = ip;
6aaeb33c 703 // switch on the bits corresponding to passed cuts
704 for (ic = 0; ic < ncuts; ic++) {
52e6652d 705 AliRsnCutSet *cuts = (AliRsnCutSet *)fTrackCuts[ic];
6aaeb33c 706 if (cuts->IsSelected(&cursor)) miniParticle.SetCutBit(ic);
707 }
708 // if a track passes at least one track cut, it is added to the pool
45aa62b9 709 if (miniParticle.CutBits()) {
710 fMiniEvent->AddParticle(miniParticle);
711 if (miniParticle.Charge() == '+') npos++;
712 else if (miniParticle.Charge() == '-') nneg++;
713 else nneu++;
714 }
6aaeb33c 715 }
52e6652d 716
6aaeb33c 717 // get number of accepted tracks
45aa62b9 718 AliDebugClass(1, Form("Event %6d: total = %5d, accepted = %4d (pos %4d, neg %4d, neu %4d)", fEvNum, npart, (Int_t)fMiniEvent->Particles().GetEntriesFast(), npos, nneg, nneu));
6aaeb33c 719}
720
3dced4f8 721//__________________________________________________________________________________________________
722Double_t AliRsnMiniAnalysisTask::ComputeAngle()
723{
724//
725// Get the plane angle
726//
727
cd273d20 728 AliEventplane *plane = 0x0;
52e6652d 729
cd273d20 730 if (fInputEvent->InheritsFrom(AliESDEvent::Class()))
731 plane = fInputEvent->GetEventplane();
732 else if (fInputEvent->InheritsFrom(AliAODEvent::Class())) {
52e6652d 733 AliAODEvent *aodEvent = (AliAODEvent *)fInputEvent;
cd273d20 734 plane = aodEvent->GetHeader()->GetEventplaneP();
735 }
736
52e6652d 737 if (plane)
3dced4f8 738 return plane->GetEventplane("Q");
739 else {
740 AliWarning("No event plane defined");
741 return 1E20;
742 }
743}
744
03d23846 745//__________________________________________________________________________________________________
746Double_t AliRsnMiniAnalysisTask::ComputeCentrality(Bool_t isESD)
747{
748//
749// Computes event centrality/multiplicity according to the criterion defined
750// by two elements: (1) choice between multiplicity and centrality and
751// (2) the string defining what criterion must be used for specific computation.
752//
753
754 if (fUseCentrality) {
755 AliCentrality *centrality = fInputEvent->GetCentrality();
756 if (!centrality) {
757 AliError("Cannot compute centrality!");
758 return -1.0;
759 }
760 return centrality->GetCentralityPercentile(fCentralityType.Data());
761 } else {
03d23846 762 if (!fCentralityType.CompareTo("TRACKS"))
763 return fInputEvent->GetNumberOfTracks();
764 else if (!fCentralityType.CompareTo("QUALITY"))
c80938f5 765 if (isESD)
52e6652d 766 return AliESDtrackCuts::GetReferenceMultiplicity((AliESDEvent *)fInputEvent, kTRUE);
c80938f5 767 else {
768 Double_t count = 0.;
769 Int_t iTrack, ntracksLoop = fInputEvent->GetNumberOfTracks();
52e6652d 770 for (iTrack = 0; iTrack < ntracksLoop; iTrack++) {
771 AliVTrack *track = (AliVTrack *)fInputEvent->GetTrack(iTrack);
772 AliAODTrack *aodt = dynamic_cast<AliAODTrack *>(track);
c80938f5 773 if (!aodt) continue;
774 if (!aodt->TestFilterBit(5)) continue;
775 count++;
776 }
777 return count;
778 }
03d23846 779 else if (!fCentralityType.CompareTo("TRACKLETS")) {
c80938f5 780 if (isESD) {
52e6652d 781 const AliMultiplicity *mult = ((AliESDEvent *)fInputEvent)->GetMultiplicity();
c80938f5 782 Float_t nClusters[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
783 for(Int_t ilay = 0; ilay < 6; ilay++) nClusters[ilay] = (Float_t)mult->GetNumberOfITSClusters(ilay);
784 return AliESDUtils::GetCorrSPD2(nClusters[1], fInputEvent->GetPrimaryVertex()->GetZ());
785 } else {
786 AliWarning("Cannot compute multiplicity with SPD tracklets from AOD");
787 return 1E20;
788 }
03d23846 789 } else {
790 AliError(Form("String '%s' does not define a possible multiplicity/centrality computation", fCentralityType.Data()));
791 return -1.0;
792 }
793 }
794}
795
796//__________________________________________________________________________________________________
797void AliRsnMiniAnalysisTask::FillTrueMotherESD(AliRsnMiniEvent *miniEvent)
798{
799//
800// Fills the histograms with true mother (ESD version)
801//
802
803 Bool_t okMatch;
804 Int_t id, ndef = fHistograms.GetEntries();
805 Int_t ip, label1, label2, npart = fMCEvent->GetNumberOfTracks();
806 static AliRsnMiniPair miniPair;
807 AliMCParticle *daughter1, *daughter2;
808 TLorentzVector p1, p2;
809 AliRsnMiniOutput *def = 0x0;
52e6652d 810
03d23846 811 for (id = 0; id < ndef; id++) {
52e6652d 812 def = (AliRsnMiniOutput *)fHistograms[id];
03d23846 813 if (!def) continue;
814 if (!def->IsMother()) continue;
815 for (ip = 0; ip < npart; ip++) {
52e6652d 816 AliMCParticle *part = (AliMCParticle *)fMCEvent->GetTrack(ip);
64129b35 817 if (part->Particle()->GetPdgCode() != def->GetMotherPDG()) continue;
03d23846 818 // check that daughters match expected species
819 if (part->Particle()->GetNDaughters() < 2) continue;
820 label1 = part->Particle()->GetDaughter(0);
821 label2 = part->Particle()->GetDaughter(1);
52e6652d 822 daughter1 = (AliMCParticle *)fMCEvent->GetTrack(label1);
823 daughter2 = (AliMCParticle *)fMCEvent->GetTrack(label2);
03d23846 824 okMatch = kFALSE;
825 if (TMath::Abs(daughter1->Particle()->GetPdgCode()) == def->GetPDG(0) && TMath::Abs(daughter2->Particle()->GetPdgCode()) == def->GetPDG(1)) {
826 okMatch = kTRUE;
827 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(0));
828 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(1));
829 } else if (TMath::Abs(daughter1->Particle()->GetPdgCode()) == def->GetPDG(1) && TMath::Abs(daughter2->Particle()->GetPdgCode()) == def->GetPDG(0)) {
830 okMatch = kTRUE;
831 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(1));
832 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(0));
833 }
834 if (!okMatch) continue;
835 // assign momenta to computation object
836 miniPair.Sum(0) = miniPair.Sum(1) = (p1 + p2);
837 miniPair.FillRef(def->GetMotherMass());
838 // do computations
45aa62b9 839 def->FillMother(&miniPair, miniEvent, &fValues);
03d23846 840 }
841 }
842}
843
844//__________________________________________________________________________________________________
845void AliRsnMiniAnalysisTask::FillTrueMotherAOD(AliRsnMiniEvent *miniEvent)
846{
847//
848// Fills the histograms with true mother (AOD version)
849//
850
851 Bool_t okMatch;
852 TClonesArray *list = fRsnEvent.GetAODList();
853 Int_t id, ndef = fHistograms.GetEntries();
854 Int_t ip, label1, label2, npart = list->GetEntries();
855 static AliRsnMiniPair miniPair;
856 AliAODMCParticle *daughter1, *daughter2;
857 TLorentzVector p1, p2;
858 AliRsnMiniOutput *def = 0x0;
52e6652d 859
03d23846 860 for (id = 0; id < ndef; id++) {
52e6652d 861 def = (AliRsnMiniOutput *)fHistograms[id];
03d23846 862 if (!def) continue;
863 if (!def->IsMother()) continue;
864 for (ip = 0; ip < npart; ip++) {
52e6652d 865 AliAODMCParticle *part = (AliAODMCParticle *)list->At(ip);
64129b35 866 if (part->GetPdgCode() != def->GetMotherPDG()) continue;
03d23846 867 // check that daughters match expected species
868 if (part->GetNDaughters() < 2) continue;
869 label1 = part->GetDaughter(0);
870 label2 = part->GetDaughter(1);
52e6652d 871 daughter1 = (AliAODMCParticle *)list->At(label1);
872 daughter2 = (AliAODMCParticle *)list->At(label2);
03d23846 873 okMatch = kFALSE;
874 if (TMath::Abs(daughter1->GetPdgCode()) == def->GetPDG(0) && TMath::Abs(daughter2->GetPdgCode()) == def->GetPDG(1)) {
875 okMatch = kTRUE;
876 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(0));
877 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(1));
878 } else if (TMath::Abs(daughter1->GetPdgCode()) == def->GetPDG(1) && TMath::Abs(daughter2->GetPdgCode()) == def->GetPDG(0)) {
879 okMatch = kTRUE;
880 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(1));
881 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(0));
882 }
883 if (!okMatch) continue;
884 // assign momenta to computation object
885 miniPair.Sum(0) = miniPair.Sum(1) = (p1 + p2);
886 miniPair.FillRef(def->GetMotherMass());
887 // do computations
45aa62b9 888 def->FillMother(&miniPair, miniEvent, &fValues);
03d23846 889 }
890 }
891}
caef2e3c 892
893//__________________________________________________________________________________________________
894Bool_t AliRsnMiniAnalysisTask::EventsMatch(AliRsnMiniEvent *event1, AliRsnMiniEvent *event2)
895{
896//
897// Check if two events are compatible.
898// If the mixing is continuous, this is true if differences in vz, mult and angle are smaller than
52e6652d 899// the specified values.
caef2e3c 900// If the mixing is binned, this is true if the events are in the same bin.
901//
902
903 if (!event1 || !event2) return kFALSE;
904 Int_t ivz1, ivz2, imult1, imult2, iangle1, iangle2;
9e7b94f5 905 Double_t dv, dm, da;
52e6652d 906
caef2e3c 907 if (fContinuousMix) {
9e7b94f5 908 dv = TMath::Abs(event1->Vz() - event2->Vz() );
909 dm = TMath::Abs(event1->Mult() - event2->Mult() );
910 da = TMath::Abs(event1->Angle() - event2->Angle());
911 if (dv > fMaxDiffVz) {
912 //AliDebugClass(2, Form("Events #%4d and #%4d don't match due to a too large diff in Vz = %f", event1->ID(), event2->ID(), dv));
913 return kFALSE;
914 }
915 if (dm > fMaxDiffMult ) {
916 //AliDebugClass(2, Form("Events #%4d and #%4d don't match due to a too large diff in Mult = %f", event1->ID(), event2->ID(), dm));
917 return kFALSE;
918 }
919 if (da > fMaxDiffAngle) {
920 //AliDebugClass(2, Form("Events #%4d and #%4d don't match due to a too large diff in Angle = %f", event1->ID(), event2->ID(), da));
921 return kFALSE;
922 }
caef2e3c 923 return kTRUE;
924 } else {
925 ivz1 = (Int_t)(event1->Vz() / fMaxDiffVz);
926 ivz2 = (Int_t)(event2->Vz() / fMaxDiffVz);
927 imult1 = (Int_t)(event1->Mult() / fMaxDiffMult);
928 imult2 = (Int_t)(event2->Mult() / fMaxDiffMult);
929 iangle1 = (Int_t)(event1->Angle() / fMaxDiffAngle);
930 iangle2 = (Int_t)(event2->Angle() / fMaxDiffAngle);
931 if (ivz1 != ivz2) return kFALSE;
932 if (imult1 != imult2) return kFALSE;
933 if (iangle1 != iangle2) return kFALSE;
934 return kTRUE;
935 }
936}
937
52e6652d 938