2 // Analysis task for 'mini' sub-package
3 // Contains all definitions needed for running an analysis:
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.
13 #include <Riostream.h>
18 #include <TStopwatch.h>
21 #include "AliEventplane.h"
22 #include "AliMultiplicity.h"
23 #include "AliTriggerAnalysis.h"
24 #include "AliAnalysisManager.h"
25 #include "AliInputEventHandler.h"
27 #include "AliESDtrackCuts.h"
28 #include "AliESDUtils.h"
30 #include "AliAODEvent.h"
31 #include "AliAODMCParticle.h"
33 #include "AliRsnCutSet.h"
34 #include "AliRsnMiniPair.h"
35 #include "AliRsnMiniEvent.h"
36 #include "AliRsnMiniParticle.h"
38 #include "AliRsnMiniAnalysisTask.h"
41 ClassImp(AliRsnMiniAnalysisTask)
43 //__________________________________________________________________________________________________
44 AliRsnMiniAnalysisTask::AliRsnMiniAnalysisTask() :
49 fUseCentrality(kFALSE),
50 fCentralityType("QUALITY"),
51 fUseAOD049CentralityPatch(kFALSE),
52 fContinuousMix(kTRUE),
58 fHistograms("AliRsnMiniOutput", 0),
59 fValues("AliRsnMiniValue", 0),
61 fHAEventsVsMulti(0x0),
63 fHAEventMultiCent(0x0),
78 // Dummy constructor ALWAYS needed for I/O.
82 //__________________________________________________________________________________________________
83 AliRsnMiniAnalysisTask::AliRsnMiniAnalysisTask(const char *name, Bool_t useMC) :
84 AliAnalysisTaskSE(name),
87 fTriggerMask(AliVEvent::kMB),
88 fUseCentrality(kFALSE),
89 fCentralityType("QUALITY"),
90 fUseAOD049CentralityPatch(kFALSE),
91 fContinuousMix(kTRUE),
97 fHistograms("AliRsnMiniOutput", 0),
98 fValues("AliRsnMiniValue", 0),
100 fHAEventsVsMulti(0x0),
102 fHAEventMultiCent(0x0),
112 fMixPrintRefresh(-1),
117 // Default constructor.
118 // Define input and output slots here (never in the dummy constructor)
119 // Input slot #0 works with a TChain - it is connected to the default input container
120 // Output slot #1 writes into a TH1 container
123 DefineOutput(1, TList::Class());
126 //__________________________________________________________________________________________________
127 AliRsnMiniAnalysisTask::AliRsnMiniAnalysisTask(const AliRsnMiniAnalysisTask ©) :
128 AliAnalysisTaskSE(copy),
131 fTriggerMask(copy.fTriggerMask),
132 fUseCentrality(copy.fUseCentrality),
133 fCentralityType(copy.fCentralityType),
134 fUseAOD049CentralityPatch(copy.fUseAOD049CentralityPatch),
135 fContinuousMix(copy.fContinuousMix),
137 fMaxDiffMult(copy.fMaxDiffMult),
138 fMaxDiffVz(copy.fMaxDiffVz),
139 fMaxDiffAngle(copy.fMaxDiffAngle),
141 fHistograms(copy.fHistograms),
142 fValues(copy.fValues),
144 fHAEventsVsMulti(0x0),
146 fHAEventMultiCent(0x0),
148 fEventCuts(copy.fEventCuts),
149 fTrackCuts(copy.fTrackCuts),
152 fTriggerAna(copy.fTriggerAna),
153 fESDtrackCuts(copy.fESDtrackCuts),
155 fBigOutput(copy.fBigOutput),
156 fMixPrintRefresh(copy.fMixPrintRefresh),
157 fMaxNDaughters(copy.fMaxNDaughters),
158 fCheckP(copy.fCheckP)
162 // Implemented as requested by C++ standards.
163 // Can be used in PROOF and by plugins.
167 //__________________________________________________________________________________________________
168 AliRsnMiniAnalysisTask &AliRsnMiniAnalysisTask::operator=(const AliRsnMiniAnalysisTask ©)
171 // Assignment operator.
172 // Implemented as requested by C++ standards.
173 // Can be used in PROOF and by plugins.
176 AliAnalysisTaskSE::operator=(copy);
179 fUseMC = copy.fUseMC;
180 fEvNum = copy.fEvNum;
181 fTriggerMask = copy.fTriggerMask;
182 fUseCentrality = copy.fUseCentrality;
183 fCentralityType = copy.fCentralityType;
184 fUseAOD049CentralityPatch = copy.fUseAOD049CentralityPatch;
185 fContinuousMix = copy.fContinuousMix;
187 fMaxDiffMult = copy.fMaxDiffMult;
188 fMaxDiffVz = copy.fMaxDiffVz;
189 fMaxDiffAngle = copy.fMaxDiffAngle;
190 fHistograms = copy.fHistograms;
191 fValues = copy.fValues;
192 fHEventStat = copy.fHEventStat;
193 fHAEventsVsMulti = copy.fHAEventsVsMulti;
194 fHAEventVz = copy.fHAEventVz;
195 fHAEventMultiCent = copy.fHAEventMultiCent;
196 fHAEventPlane = copy.fHAEventPlane;
197 fEventCuts = copy.fEventCuts;
198 fTrackCuts = copy.fTrackCuts;
199 fTriggerAna = copy.fTriggerAna;
200 fESDtrackCuts = copy.fESDtrackCuts;
201 fBigOutput = copy.fBigOutput;
202 fMixPrintRefresh = copy.fMixPrintRefresh;
203 fMaxNDaughters = copy.fMaxNDaughters;
204 fCheckP = copy.fCheckP;
208 //__________________________________________________________________________________________________
209 AliRsnMiniAnalysisTask::~AliRsnMiniAnalysisTask()
213 // Clean-up the output list, but not the histograms that are put inside
214 // (the list is owner and will clean-up these histograms). Protect in PROOF case.
218 if (fOutput && !AliAnalysisManager::GetAnalysisManager()->IsProofMode()) {
224 //__________________________________________________________________________________________________
225 Int_t AliRsnMiniAnalysisTask::AddTrackCuts(AliRsnCutSet *cuts)
228 // Add a new cut set for a new criterion for track selection.
229 // A user can add as many as he wants, and each one corresponds
230 // to one of the available bits in the AliRsnMiniParticle mask.
231 // The only check is the following: if a cut set with the same name
232 // as the argument is there, this is not added.
233 // Return value is the array position of this set.
236 TObject *obj = fTrackCuts.FindObject(cuts->GetName());
239 AliInfo(Form("A cut set named '%s' already exists", cuts->GetName()));
240 return fTrackCuts.IndexOf(obj);
242 fTrackCuts.AddLast(cuts);
243 return fTrackCuts.IndexOf(cuts);
247 //__________________________________________________________________________________________________
248 void AliRsnMiniAnalysisTask::UserCreateOutputObjects()
251 // Initialization of outputs.
252 // This is called once per worker node.
259 AliInfo(Form("Selected event characterization: %s (%s)", (fUseCentrality ? "centrality" : "multiplicity"), fCentralityType.Data()));
261 // initialize trigger analysis
262 if (fTriggerAna) delete fTriggerAna;
263 fTriggerAna = new AliTriggerAnalysis;
265 // initialize ESD quality cuts
266 if (fESDtrackCuts) delete fESDtrackCuts;
267 fESDtrackCuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2010();
269 // create list and set it as owner of its content (MANDATORY)
270 if (fBigOutput) OpenFile(1);
271 fOutput = new TList();
274 // initialize event statistics counter
275 fHEventStat = new TH1F("hEventStat", "Event statistics", 4, 0.0, 4.0);
276 fHEventStat->GetXaxis()->SetBinLabel(1, "CINT1B");
277 fHEventStat->GetXaxis()->SetBinLabel(2, "V0AND");
278 fHEventStat->GetXaxis()->SetBinLabel(3, "Candle");
279 fHEventStat->GetXaxis()->SetBinLabel(4, "Accepted");
280 fOutput->Add(fHEventStat);
283 fHAEventsVsMulti = new TH1F("hAEventsVsMulti", "Accepted events vs Centrality", 100, 0, 100.0);
285 fHAEventsVsMulti = new TH1F("hAEventsVsMulti", "Accepted events vs Multiplicity",1000, 0, 1000.0);
286 fOutput->Add(fHAEventsVsMulti);
288 if(fHAEventVz) fOutput->Add(fHAEventVz);
289 if(fHAEventMultiCent) fOutput->Add(fHAEventMultiCent);
290 if(fHAEventPlane) fOutput->Add(fHAEventPlane);
292 TIter next(&fTrackCuts);
294 while ((cs = (AliRsnCutSet *) next())) {
298 // create temporary tree for filtered events
299 if (fMiniEvent) delete fMiniEvent;
300 fEvBuffer = new TTree("EventBuffer", "Temporary buffer for mini events");
301 fEvBuffer->Branch("events", "AliRsnMiniEvent", &fMiniEvent);
303 // create one histogram per each stored definition (event histograms)
304 Int_t i, ndef = fHistograms.GetEntries();
305 AliRsnMiniOutput *def = 0x0;
306 for (i = 0; i < ndef; i++) {
307 def = (AliRsnMiniOutput *)fHistograms[i];
309 if (!def->Init(GetName(), fOutput)) {
310 AliError(Form("Def '%s': failed initialization", def->GetName()));
315 // post data for ALL output slots >0 here, to get at least an empty histogram
316 PostData(1, fOutput);
319 //__________________________________________________________________________________________________
320 void AliRsnMiniAnalysisTask::UserExec(Option_t *)
324 // In this case, it checks if the event is acceptable, and eventually
325 // creates the corresponding mini-event and stores it in the buffer.
326 // The real histogram filling is done at the end, in "FinishTaskOutput".
329 // increment event counter
332 // check current event
333 Char_t check = CheckCurrentEvent();
336 // setup PID response
337 AliAnalysisManager *man = AliAnalysisManager::GetAnalysisManager();
338 AliInputEventHandler *inputHandler = (AliInputEventHandler *)man->GetInputEventHandler();
339 fRsnEvent.SetPIDResponse(inputHandler->GetPIDResponse());
341 // fill a mini-event from current
342 // and skip this event if no tracks were accepted
343 FillMiniEvent(check);
345 // fill MC based histograms on mothers,
346 // which do need the original event
348 if (fRsnEvent.IsESD() && fMCEvent)
349 FillTrueMotherESD(fMiniEvent);
350 else if (fRsnEvent.IsAOD() && fRsnEvent.GetAODList())
351 FillTrueMotherAOD(fMiniEvent);
354 // if the event is not empty, store it
355 if (fMiniEvent->IsEmpty()) {
356 AliDebugClass(2, Form("Rejecting empty event #%d", fEvNum));
358 Int_t id = fEvBuffer->GetEntries();
359 AliDebugClass(2, Form("Adding event #%d with ID = %d", fEvNum, id));
360 fMiniEvent->ID() = id;
364 // post data for computed stuff
365 PostData(1, fOutput);
368 //__________________________________________________________________________________________________
369 void AliRsnMiniAnalysisTask::FinishTaskOutput()
372 // This function is called at the end of the loop on available events,
373 // and then the buffer will be full with all the corresponding mini-events,
374 // each one containing all tracks selected by each of the available track cuts.
375 // Here a loop is done on each of these events, and both single-event and mixing are computed
378 // security code: reassign the buffer to the mini-event cursor
379 fEvBuffer->SetBranchAddress("events", &fMiniEvent);
382 Int_t ievt, nEvents = (Int_t)fEvBuffer->GetEntries();
383 Int_t idef, nDefs = fHistograms.GetEntries();
384 Int_t imix, iloop, ifill;
385 AliRsnMiniOutput *def = 0x0;
386 AliRsnMiniOutput::EComputation compType;
388 Int_t printNum = fMixPrintRefresh;
390 if (nEvents>1e5) printNum=nEvents/100;
391 else if (nEvents>1e4) printNum=nEvents/10;
395 // loop on events, and for each one fill all outputs
396 // using the appropriate procedure depending on its type
397 // only mother-related histograms are filled in UserExec,
398 // since they require direct access to MC event
400 for (ievt = 0; ievt < nEvents; ievt++) {
402 fEvBuffer->GetEntry(ievt);
403 if (printNum&&(ievt%printNum==0)) {
404 AliInfo(Form("[%s] Std.Event %d/%d",GetName(), ievt,nEvents));
405 timer.Stop(); timer.Print(); fflush(stdout); timer.Start(kFALSE);
408 for (idef = 0; idef < nDefs; idef++) {
409 def = (AliRsnMiniOutput *)fHistograms[idef];
411 compType = def->GetComputation();
412 // execute computation in the appropriate way
414 case AliRsnMiniOutput::kEventOnly:
415 //AliDebugClass(1, Form("Event %d, def '%s': event-value histogram filling", ievt, def->GetName()));
417 def->FillEvent(fMiniEvent, &fValues);
419 case AliRsnMiniOutput::kTruePair:
420 //AliDebugClass(1, Form("Event %d, def '%s': true-pair histogram filling", ievt, def->GetName()));
421 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
423 case AliRsnMiniOutput::kTrackPair:
424 //AliDebugClass(1, Form("Event %d, def '%s': pair-value histogram filling", ievt, def->GetName()));
425 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
427 case AliRsnMiniOutput::kTrackPairRotated1:
428 //AliDebugClass(1, Form("Event %d, def '%s': rotated (1) background histogram filling", ievt, def->GetName()));
429 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
431 case AliRsnMiniOutput::kTrackPairRotated2:
432 //AliDebugClass(1, Form("Event %d, def '%s': rotated (2) background histogram filling", ievt, def->GetName()));
433 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
436 // other kinds are processed elsewhere
438 AliDebugClass(2, Form("Computation = %d", (Int_t)compType));
441 AliDebugClass(1, Form("Event %6d: def = '%15s' -- fills = %5d", ievt, def->GetName(), ifill));
445 // if no mixing is required, stop here and post the output
447 AliDebugClass(2, "Stopping here, since no mixing is required");
448 PostData(1, fOutput);
452 // initialize mixing counter
453 Int_t nmatched[nEvents];
454 TString *smatched = new TString[nEvents];
455 for (ievt = 0; ievt < nEvents; ievt++) {
456 smatched[ievt] = "|";
461 AliInfo(Form("[%s] Std.Event %d/%d",GetName(), nEvents,nEvents));
462 timer.Stop(); timer.Print(); timer.Start(); fflush(stdout);
464 // search for good matchings
465 for (ievt = 0; ievt < nEvents; ievt++) {
466 if (printNum&&(ievt%printNum==0)) {
467 AliInfo(Form("[%s] EventMixing searching %d/%d",GetName(),ievt,nEvents));
468 timer.Stop(); timer.Print(); timer.Start(kFALSE); fflush(stdout);
470 if (nmatched[ievt] >= fNMix) continue;
471 fEvBuffer->GetEntry(ievt);
472 AliRsnMiniEvent evMain(*fMiniEvent);
473 for (iloop = 1; iloop < nEvents; iloop++) {
475 if (imix >= nEvents) imix -= nEvents;
476 if (imix == ievt) continue;
478 fEvBuffer->GetEntry(imix);
479 // skip if events are not matched
480 if (!EventsMatch(&evMain, fMiniEvent)) continue;
481 // check that the array of good matches for mixed does not already contain main event
482 if (smatched[imix].Contains(Form("|%d|", ievt))) continue;
483 // check that the found good events has not enough matches already
484 if (nmatched[imix] >= fNMix) continue;
485 // add new mixing candidate
486 smatched[ievt].Append(Form("%d|", imix));
489 if (nmatched[ievt] >= fNMix) break;
491 AliDebugClass(1, Form("Matches for event %5d = %d [%s] (missing are declared above)", evMain.ID(), nmatched[ievt], smatched[ievt].Data()));
494 AliInfo(Form("[%s] EventMixing searching %d/%d",GetName(),nEvents,nEvents));
495 timer.Stop(); timer.Print(); fflush(stdout); timer.Start();
498 TObjArray *list = 0x0;
499 TObjString *os = 0x0;
500 for (ievt = 0; ievt < nEvents; ievt++) {
501 if (printNum&&(ievt%printNum==0)) {
502 AliInfo(Form("[%s] EventMixing %d/%d",GetName(),ievt,nEvents));
503 timer.Stop(); timer.Print(); timer.Start(kFALSE); fflush(stdout);
506 fEvBuffer->GetEntry(ievt);
507 AliRsnMiniEvent evMain(*fMiniEvent);
508 list = smatched[ievt].Tokenize("|");
509 TObjArrayIter next(list);
510 while ( (os = (TObjString *)next()) ) {
511 imix = os->GetString().Atoi();
512 fEvBuffer->GetEntry(imix);
513 for (idef = 0; idef < nDefs; idef++) {
514 def = (AliRsnMiniOutput *)fHistograms[idef];
516 if (!def->IsTrackPairMix()) continue;
517 ifill += def->FillPair(&evMain, fMiniEvent, &fValues, kTRUE);
518 if (!def->IsSymmetric()) {
519 AliDebugClass(2, "Reflecting non symmetric pair");
520 ifill += def->FillPair(fMiniEvent, &evMain, &fValues, kFALSE);
529 AliInfo(Form("[%s] EventMixing %d/%d",GetName(),nEvents,nEvents));
530 timer.Stop(); timer.Print(); fflush(stdout);
535 for (iloop = 1; iloop < nEvents; iloop++) {
537 // restart from beginning if reached last event
538 if (imix >= nEvents) imix -= nEvents;
539 // avoid to mix an event with itself
540 if (imix == ievt) continue;
541 // skip all events already mixed enough times
542 if (fNMixed[ievt] >= fNMix) break;
543 if (fNMixed[imix] >= fNMix) continue;
544 fEvBuffer->GetEntry(imix);
545 // skip if events are not matched
546 if (TMath::Abs(evMain.Vz() - fMiniEvent->Vz() ) > fMaxDiffVz ) continue;
547 if (TMath::Abs(evMain.Mult() - fMiniEvent->Mult() ) > fMaxDiffMult ) continue;
548 if (TMath::Abs(evMain.Angle() - fMiniEvent->Angle()) > fMaxDiffAngle) continue;
549 // found a match: increment counter for both events
550 AliDebugClass(1, Form("Event %d, def '%s': event mixing (%d with %d)", ievt, def->GetName(), ievt, imix));
554 ifill += def->FillPair(&evMain, fMiniEvent, &fValues);
555 // stop if mixed enough times
556 if (fNMixed[ievt] >= fNMix) break;
559 // print number of mixings done with each event
560 for (ievt = 0; ievt < nEvents; ievt++) {
561 AliDebugClass(2, Form("Event %6d: mixed %2d times", ievt, fNMixed[ievt]));
565 // post computed data
566 PostData(1, fOutput);
569 //__________________________________________________________________________________________________
570 void AliRsnMiniAnalysisTask::Terminate(Option_t *)
573 // Draw result to screen, or perform fitting, normalizations
574 // Called once at the end of the query
577 fOutput = dynamic_cast<TList *>(GetOutputData(1));
579 AliError("Could not retrieve TList fOutput");
584 //__________________________________________________________________________________________________
585 Char_t AliRsnMiniAnalysisTask::CheckCurrentEvent()
588 // This method checks if current event is OK for analysis.
589 // In case it is, the pointers of the local AliRsnEvent data member
590 // will point to it, in order to allow cut checking, otherwise the
591 // function exits with a failure message.
593 // ESD events must pass the physics selection, AOD are supposed to do.
595 // While checking the event, a histogram is filled to count the number
596 // of CINT1B, V0AND and CANDLE events, which are needed for normalization
598 // Return values can be:
599 // -- 'E' if the event is accepted and is ESD
600 // -- 'A' if the event is accepted and is AOD
601 // -- 0 if the event is not accepted
604 // string to sum messages
608 // exit points are provided in all cases an event is bad
609 // if this block is passed, an event can be rejected only
610 // if it does not pass the set of event cuts defined in the task
613 if (fInputEvent->InheritsFrom(AliESDEvent::Class())) {
616 // ESD specific check: Physics Selection
617 // --> if this is failed, the event is rejected
618 isSelected = (((AliInputEventHandler *)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))->IsEventSelected() & fTriggerMask);
621 AliDebugClass(2, "Event does not pass physics selections");
622 fRsnEvent.SetRef(0x0);
623 fRsnEvent.SetRefMC(0x0);
626 // set reference to input
627 fRsnEvent.SetRef(fInputEvent);
628 // add MC if requested and available
631 fRsnEvent.SetRefMC(fMCEvent);
633 AliWarning("MC event requested but not available");
634 fRsnEvent.SetRefMC(0x0);
637 } else if (fInputEvent->InheritsFrom(AliAODEvent::Class())) {
640 // set reference to input
641 fRsnEvent.SetRef(fInputEvent);
642 // add MC if requested and available (it is in the same object)
644 fRsnEvent.SetRefMC(fInputEvent);
645 if (!fRsnEvent.GetAODList()) {
646 AliWarning("MC event requested but not available");
647 fRsnEvent.SetRefMC(0x0);
651 AliError(Form("Bad input event class: %s", fInputEvent->ClassName()));
652 // reset pointers in local AliRsnEvent object
653 fRsnEvent.SetRef(0x0);
654 fRsnEvent.SetRefMC(0x0);
658 // fill counter of accepted events
659 fHEventStat->Fill(0.1);
661 // check if it is V0AND
662 // --> uses a cast to AliESDEvent even if the input is an AliAODEvent
663 Bool_t v0A = fTriggerAna->IsOfflineTriggerFired((AliESDEvent *)fInputEvent, AliTriggerAnalysis::kV0A);
664 Bool_t v0C = fTriggerAna->IsOfflineTriggerFired((AliESDEvent *)fInputEvent, AliTriggerAnalysis::kV0C);
666 msg += " -- VOAND = YES";
667 fHEventStat->Fill(1.1);
669 msg += " -- VOAND = NO ";
673 // --> requires at least one good quality track with Pt > 0.5 and |eta| <= 0.8
674 Int_t iTrack, ntracksLoop = fInputEvent->GetNumberOfTracks();
675 Bool_t candle = kFALSE;
676 for (iTrack = 0; iTrack < ntracksLoop; iTrack++) {
677 AliVTrack *track = (AliVTrack *)fInputEvent->GetTrack(iTrack);
678 AliESDtrack *esdt = dynamic_cast<AliESDtrack *>(track);
679 AliAODTrack *aodt = dynamic_cast<AliAODTrack *>(track);
680 if (track->Pt() < 0.5) continue;
681 if(TMath::Abs(track->Eta()) > 0.8) continue;
682 if (esdt) if (!fESDtrackCuts->AcceptTrack(esdt)) continue;
683 if (aodt) if (!aodt->TestFilterBit(5)) continue;
688 msg += " -- CANDLE = YES";
689 fHEventStat->Fill(2.1);
691 msg += " -- CANDLE = NO ";
694 // if event cuts are defined, they are checked here
695 // final decision on the event depends on this
698 if (!fEventCuts->IsSelected(&fRsnEvent)) {
699 msg += " -- Local cuts = REJECTED";
702 msg += " -- Local cuts = ACCEPTED";
706 msg += " -- Local cuts = NONE";
710 // if the above exit point is not taken, the event is accepted
711 AliDebugClass(2, Form("Stats: %s", msg.Data()));
713 fHEventStat->Fill(3.1);
714 Double_t multi = ComputeCentrality((output == 'E'));
715 fHAEventsVsMulti->Fill(multi);
716 if(fHAEventVz) fHAEventVz->Fill(multi,fInputEvent->GetPrimaryVertex()->GetZ());
717 if(fHAEventMultiCent) fHAEventMultiCent->Fill(multi,ComputeMultiplicity(output == 'E',fHAEventMultiCent->GetYaxis()->GetTitle()));
718 if(fHAEventPlane) fHAEventPlane->Fill(multi,ComputeAngle());
725 //__________________________________________________________________________________________________
726 void AliRsnMiniAnalysisTask::FillMiniEvent(Char_t evType)
729 // Refresh cursor mini-event data member to fill with current event.
730 // Returns the total number of tracks selected.
733 // assign event-related values
734 if (fMiniEvent) delete fMiniEvent;
735 fMiniEvent = new AliRsnMiniEvent;
736 fMiniEvent->Vz() = fInputEvent->GetPrimaryVertex()->GetZ();
737 fMiniEvent->Angle() = ComputeAngle();
738 fMiniEvent->Mult() = ComputeCentrality((evType == 'E'));
739 AliDebugClass(2, Form("Event %d: type = %c -- vz = %f -- mult = %f -- angle = %f", fEvNum, evType, fMiniEvent->Vz(), fMiniEvent->Mult(), fMiniEvent->Angle()));
741 // loop on daughters and assign track-related values
742 Int_t ic, ncuts = fTrackCuts.GetEntries();
743 Int_t ip, npart = fRsnEvent.GetAbsoluteSum();
744 Int_t npos = 0, nneg = 0, nneu = 0;
745 AliRsnDaughter cursor;
746 AliRsnMiniParticle miniParticle;
747 for (ip = 0; ip < npart; ip++) {
748 // point cursor to next particle
749 fRsnEvent.SetDaughter(cursor, ip);
750 // copy momentum and MC info if present
751 miniParticle.CopyDaughter(&cursor);
752 miniParticle.Index() = ip;
753 // switch on the bits corresponding to passed cuts
754 for (ic = 0; ic < ncuts; ic++) {
755 AliRsnCutSet *cuts = (AliRsnCutSet *)fTrackCuts[ic];
756 if (cuts->IsSelected(&cursor)) miniParticle.SetCutBit(ic);
758 // if a track passes at least one track cut, it is added to the pool
759 if (miniParticle.CutBits()) {
760 fMiniEvent->AddParticle(miniParticle);
761 if (miniParticle.Charge() == '+') npos++;
762 else if (miniParticle.Charge() == '-') nneg++;
767 // get number of accepted tracks
768 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));
771 //__________________________________________________________________________________________________
772 Double_t AliRsnMiniAnalysisTask::ComputeAngle()
775 // Get the plane angle
778 AliEventplane *plane = 0x0;
780 if (fInputEvent->InheritsFrom(AliESDEvent::Class()))
781 plane = fInputEvent->GetEventplane();
782 else if (fInputEvent->InheritsFrom(AliAODEvent::Class())) {
783 AliAODEvent *aodEvent = (AliAODEvent *)fInputEvent;
784 plane = aodEvent->GetHeader()->GetEventplaneP();
788 return plane->GetEventplane("Q");
790 AliWarning("No event plane defined");
795 //__________________________________________________________________________________________________
796 Double_t AliRsnMiniAnalysisTask::ComputeCentrality(Bool_t isESD)
799 // Computes event centrality/multiplicity according to the criterion defined
800 // by two elements: (1) choice between multiplicity and centrality and
801 // (2) the string defining what criterion must be used for specific computation.
804 if (fUseCentrality) {
806 if ((!fUseMC) && (!isESD) && (fUseAOD049CentralityPatch)) {
807 return ApplyCentralityPatchAOD049();
809 AliCentrality *centrality = fInputEvent->GetCentrality();
811 AliError("Cannot compute centrality!");
814 return centrality->GetCentralityPercentile(fCentralityType.Data());
817 if (!fCentralityType.CompareTo("TRACKS"))
818 return fInputEvent->GetNumberOfTracks();
819 else if (!fCentralityType.CompareTo("QUALITY"))
821 return AliESDtrackCuts::GetReferenceMultiplicity((AliESDEvent *)fInputEvent, kTRUE);
824 Int_t iTrack, ntracksLoop = fInputEvent->GetNumberOfTracks();
825 for (iTrack = 0; iTrack < ntracksLoop; iTrack++) {
826 AliVTrack *track = (AliVTrack *)fInputEvent->GetTrack(iTrack);
827 AliAODTrack *aodt = dynamic_cast<AliAODTrack *>(track);
829 if (!aodt->TestFilterBit(5)) continue;
834 else if (!fCentralityType.CompareTo("TRACKLETS")) {
836 const AliMultiplicity *mult = ((AliESDEvent *)fInputEvent)->GetMultiplicity();
837 Float_t nClusters[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
838 for(Int_t ilay = 0; ilay < 6; ilay++) nClusters[ilay] = (Float_t)mult->GetNumberOfITSClusters(ilay);
839 return AliESDUtils::GetCorrSPD2(nClusters[1], fInputEvent->GetPrimaryVertex()->GetZ());
841 AliWarning("Cannot compute multiplicity with SPD tracklets from AOD");
845 AliError(Form("String '%s' does not define a possible multiplicity/centrality computation", fCentralityType.Data()));
851 //__________________________________________________________________________________________________
852 Double_t AliRsnMiniAnalysisTask::ComputeMultiplicity(Bool_t isESD,TString type)
855 // Computes event multiplicity according to the string defining
856 // what criterion must be used for specific computation.
861 if (!type.CompareTo("TRACKS"))
862 return fInputEvent->GetNumberOfTracks();
863 else if (!type.CompareTo("QUALITY"))
865 return AliESDtrackCuts::GetReferenceMultiplicity((AliESDEvent *)fInputEvent, kTRUE);
868 Int_t iTrack, ntracksLoop = fInputEvent->GetNumberOfTracks();
869 for (iTrack = 0; iTrack < ntracksLoop; iTrack++) {
870 AliVTrack *track = (AliVTrack *)fInputEvent->GetTrack(iTrack);
871 AliAODTrack *aodt = dynamic_cast<AliAODTrack *>(track);
873 if (!aodt->TestFilterBit(5)) continue;
878 else if (!type.CompareTo("TRACKLETS")) {
880 const AliMultiplicity *mult = ((AliESDEvent *)fInputEvent)->GetMultiplicity();
881 Float_t nClusters[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
882 for(Int_t ilay = 0; ilay < 6; ilay++) nClusters[ilay] = (Float_t)mult->GetNumberOfITSClusters(ilay);
883 return AliESDUtils::GetCorrSPD2(nClusters[1], fInputEvent->GetPrimaryVertex()->GetZ());
885 AliWarning("Cannot compute multiplicity with SPD tracklets from AOD");
889 AliError(Form("String '%s' does not define a possible multiplicity/centrality computation", type.Data()));
896 //__________________________________________________________________________________________________
897 void AliRsnMiniAnalysisTask::FillTrueMotherESD(AliRsnMiniEvent *miniEvent)
900 // Fills the histograms with true mother (ESD version)
904 Int_t id, ndef = fHistograms.GetEntries();
905 Int_t ip, label1, label2, npart = fMCEvent->GetNumberOfTracks();
906 static AliRsnMiniPair miniPair;
907 AliMCParticle *daughter1, *daughter2;
908 TLorentzVector p1, p2;
909 AliRsnMiniOutput *def = 0x0;
911 for (id = 0; id < ndef; id++) {
912 def = (AliRsnMiniOutput *)fHistograms[id];
914 if (!def->IsMother()) continue;
915 for (ip = 0; ip < npart; ip++) {
916 AliMCParticle *part = (AliMCParticle *)fMCEvent->GetTrack(ip);
917 //get mother pdg code
918 if (part->Particle()->GetPdgCode() != def->GetMotherPDG()) continue;
919 // check that daughters match expected species
920 if (part->Particle()->GetNDaughters() < 2) continue;
921 if (fMaxNDaughters > 0 && part->Particle()->GetNDaughters() > fMaxNDaughters) continue;
922 label1 = part->Particle()->GetDaughter(0);
923 label2 = part->Particle()->GetDaughter(1);
924 daughter1 = (AliMCParticle *)fMCEvent->GetTrack(label1);
925 daughter2 = (AliMCParticle *)fMCEvent->GetTrack(label2);
927 if (TMath::Abs(daughter1->Particle()->GetPdgCode()) == def->GetPDG(0) && TMath::Abs(daughter2->Particle()->GetPdgCode()) == def->GetPDG(1)) {
929 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(0));
930 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(1));
931 } else if (TMath::Abs(daughter1->Particle()->GetPdgCode()) == def->GetPDG(1) && TMath::Abs(daughter2->Particle()->GetPdgCode()) == def->GetPDG(0)) {
933 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(1));
934 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(0));
936 if (!okMatch) continue;
937 if(fCheckP && (TMath::Abs(part->Px()-(daughter1->Px()+daughter2->Px()))/(TMath::Abs(part->Px())+1.e-13)) > 0.00001 &&
938 (TMath::Abs(part->Py()-(daughter1->Py()+daughter2->Py()))/(TMath::Abs(part->Py())+1.e-13)) > 0.00001 &&
939 (TMath::Abs(part->Pz()-(daughter1->Pz()+daughter2->Pz()))/(TMath::Abs(part->Pz())+1.e-13)) > 0.00001 ) continue;
940 // assign momenta to computation object
941 miniPair.Sum(0) = miniPair.Sum(1) = (p1 + p2);
942 miniPair.FillRef(def->GetMotherMass());
944 def->FillMother(&miniPair, miniEvent, &fValues);
949 //__________________________________________________________________________________________________
950 void AliRsnMiniAnalysisTask::FillTrueMotherAOD(AliRsnMiniEvent *miniEvent)
953 // Fills the histograms with true mother (AOD version)
957 TClonesArray *list = fRsnEvent.GetAODList();
958 Int_t id, ndef = fHistograms.GetEntries();
959 Int_t ip, label1, label2, npart = list->GetEntries();
960 static AliRsnMiniPair miniPair;
961 AliAODMCParticle *daughter1, *daughter2;
962 TLorentzVector p1, p2;
963 AliRsnMiniOutput *def = 0x0;
965 for (id = 0; id < ndef; id++) {
966 def = (AliRsnMiniOutput *)fHistograms[id];
968 if (!def->IsMother()) continue;
969 for (ip = 0; ip < npart; ip++) {
970 AliAODMCParticle *part = (AliAODMCParticle *)list->At(ip);
971 if (part->GetPdgCode() != def->GetMotherPDG()) continue;
972 // check that daughters match expected species
973 if (part->GetNDaughters() < 2) continue;
974 if (fMaxNDaughters > 0 && part->GetNDaughters() > fMaxNDaughters) continue;
975 label1 = part->GetDaughter(0);
976 label2 = part->GetDaughter(1);
977 daughter1 = (AliAODMCParticle *)list->At(label1);
978 daughter2 = (AliAODMCParticle *)list->At(label2);
980 if (TMath::Abs(daughter1->GetPdgCode()) == def->GetPDG(0) && TMath::Abs(daughter2->GetPdgCode()) == def->GetPDG(1)) {
982 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(0));
983 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(1));
984 } else if (TMath::Abs(daughter1->GetPdgCode()) == def->GetPDG(1) && TMath::Abs(daughter2->GetPdgCode()) == def->GetPDG(0)) {
986 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(1));
987 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(0));
989 if (!okMatch) continue;
990 if(fCheckP && (TMath::Abs(part->Px()-(daughter1->Px()+daughter2->Px()))/(TMath::Abs(part->Px())+1.e-13)) > 0.00001 &&
991 (TMath::Abs(part->Py()-(daughter1->Py()+daughter2->Py()))/(TMath::Abs(part->Py())+1.e-13)) > 0.00001 &&
992 (TMath::Abs(part->Pz()-(daughter1->Pz()+daughter2->Pz()))/(TMath::Abs(part->Pz())+1.e-13)) > 0.00001 ) continue;
994 // assign momenta to computation object
995 miniPair.Sum(0) = miniPair.Sum(1) = (p1 + p2);
996 miniPair.FillRef(def->GetMotherMass());
998 def->FillMother(&miniPair, miniEvent, &fValues);
1003 //__________________________________________________________________________________________________
1004 Bool_t AliRsnMiniAnalysisTask::EventsMatch(AliRsnMiniEvent *event1, AliRsnMiniEvent *event2)
1007 // Check if two events are compatible.
1008 // If the mixing is continuous, this is true if differences in vz, mult and angle are smaller than
1009 // the specified values.
1010 // If the mixing is binned, this is true if the events are in the same bin.
1013 if (!event1 || !event2) return kFALSE;
1014 Int_t ivz1, ivz2, imult1, imult2, iangle1, iangle2;
1015 Double_t dv, dm, da;
1017 if (fContinuousMix) {
1018 dv = TMath::Abs(event1->Vz() - event2->Vz() );
1019 dm = TMath::Abs(event1->Mult() - event2->Mult() );
1020 da = TMath::Abs(event1->Angle() - event2->Angle());
1021 if (dv > fMaxDiffVz) {
1022 //AliDebugClass(2, Form("Events #%4d and #%4d don't match due to a too large diff in Vz = %f", event1->ID(), event2->ID(), dv));
1025 if (dm > fMaxDiffMult ) {
1026 //AliDebugClass(2, Form("Events #%4d and #%4d don't match due to a too large diff in Mult = %f", event1->ID(), event2->ID(), dm));
1029 if (da > fMaxDiffAngle) {
1030 //AliDebugClass(2, Form("Events #%4d and #%4d don't match due to a too large diff in Angle = %f", event1->ID(), event2->ID(), da));
1035 ivz1 = (Int_t)(event1->Vz() / fMaxDiffVz);
1036 ivz2 = (Int_t)(event2->Vz() / fMaxDiffVz);
1037 imult1 = (Int_t)(event1->Mult() / fMaxDiffMult);
1038 imult2 = (Int_t)(event2->Mult() / fMaxDiffMult);
1039 iangle1 = (Int_t)(event1->Angle() / fMaxDiffAngle);
1040 iangle2 = (Int_t)(event2->Angle() / fMaxDiffAngle);
1041 if (ivz1 != ivz2) return kFALSE;
1042 if (imult1 != imult2) return kFALSE;
1043 if (iangle1 != iangle2) return kFALSE;
1049 //---------------------------------------------------------------------
1050 Double_t AliRsnMiniAnalysisTask::ApplyCentralityPatchAOD049()
1053 //Apply centrality patch for AOD049 outliers
1055 if (fInputEvent->InheritsFrom(AliESDEvent::Class())) {
1056 AliWarning("Requested patch for AOD049 for ESD. ");
1060 if (fCentralityType!="V0M") {
1061 AliWarning("Requested patch forAOD049 for wrong value (not centrality from V0).");
1065 AliCentrality *centrality = fInputEvent->GetCentrality();
1067 AliWarning("Cannot get centrality from AOD event.");
1071 Float_t cent = (Float_t)(centrality->GetCentralityPercentile("V0M"));
1073 Bool_t isSelRun = kFALSE;
1074 Int_t selRun[5] = {138364, 138826, 138828, 138836, 138871};
1076 Int_t quality = centrality->GetQuality();
1078 cent=(Float_t)centrality->GetCentralityPercentileUnchecked("V0M");
1080 Int_t runnum=aodEvent->GetRunNumber();
1081 for(Int_t ir=0;ir<5;ir++){
1082 if(runnum==selRun[ir]){
1087 if((quality==8||quality==9)&&isSelRun) cent=(Float_t)centrality->GetCentralityPercentileUnchecked("V0M");
1094 AliAODEvent *aodEvent = (AliAODEvent *)fInputEvent;
1095 AliAODVZERO *aodV0 = (AliAODVZERO *) aodEvent->GetVZEROData();
1096 v0+=aodV0->GetMTotV0A();
1097 v0+=aodV0->GetMTotV0C();
1098 if ( (cent==0) && (v0<19500) ) {
1099 AliDebug(3, Form("Filtering issue in centrality -> cent = %5.2f",cent));
1102 Float_t tkl = (Float_t)(aodEvent->GetTracklets()->GetNumberOfTracklets());
1103 Float_t val = 1.30552 + 0.147931 * v0;
1105 Float_t tklSigma[101] = {176.644, 156.401, 153.789, 153.015, 142.476, 137.951, 136.127, 129.852, 127.436, 124.86,
1106 120.788, 115.611, 113.172, 110.496, 109.127, 104.421, 102.479, 99.9766, 97.5152, 94.0654,
1107 92.4602, 89.3364, 87.1342, 83.3497, 82.6216, 81.1084, 78.0793, 76.1234, 72.9434, 72.1334,
1108 68.0056, 68.2755, 66.0376, 62.9666, 62.4274, 59.65, 58.3776, 56.6361, 54.5184, 53.4224,
1109 51.932, 50.8922, 48.2848, 47.912, 46.5717, 43.4114, 43.2083, 41.3065, 40.1863, 38.5255,
1110 37.2851, 37.5396, 34.4949, 33.8366, 31.8043, 31.7412, 30.8392, 30.0274, 28.8793, 27.6398,
1111 26.6488, 25.0183, 25.1489, 24.4185, 22.9107, 21.2002, 21.6977, 20.1242, 20.4963, 19.0235,
1112 19.298, 17.4103, 16.868, 15.2939, 15.2939, 16.0295, 14.186, 14.186, 15.2173, 12.9504, 12.9504,
1113 12.9504, 15.264, 12.3674, 12.3674, 12.3674, 12.3674, 12.3674, 18.3811, 13.7544, 13.7544,
1114 13.7544, 13.7544, 13.7544, 13.7544, 13.7544, 13.7544, 13.7544, 13.7544, 13.7544, 13.7544
1117 if ( TMath::Abs(tkl-val) > 6.*tklSigma[(Int_t)cent] ) {
1118 AliDebug(3, Form("Outlier event in centrality -> cent = %5.2f",cent));
1122 //force it to be -999. whatever the negative value was
1128 //----------------------------------------------------------------------------------
1129 void AliRsnMiniAnalysisTask::SetEventQAHist(TString type,TH2F *histo)
1132 AliWarning(Form("event QA histogram pointer not defined for slot %s",type.Data()));
1138 if(!type.CompareTo("vz")) fHAEventVz = histo;
1139 else if(!type.CompareTo("multicent")) {
1140 TString mtype(histo->GetYaxis()->GetTitle());
1142 if(mtype.CompareTo("QUALITY") && mtype.CompareTo("TRACKS") && mtype.CompareTo("TRACKLETS")) {
1143 AliWarning(Form("multiplicity vs. centrality histogram y-axis %s unknown, setting to TRACKS",mtype.Data()));
1144 histo->GetYaxis()->SetTitle("TRACKS");
1146 fHAEventMultiCent = histo;
1148 else if(!type.CompareTo("eventplane")) fHAEventPlane = histo;
1149 else AliWarning(Form("event QA histogram slot %s undefined",type.Data()));
1154 //----------------------------------------------------------------------------------
1155 Int_t AliRsnMiniAnalysisTask::CreateValue(AliRsnMiniValue::EType type, Bool_t useMC)
1158 // Create a new value in the task,
1159 // and returns its ID, which is needed for setting up histograms.
1160 // If that value was already initialized, returns its ID and does not recreate it.
1163 Int_t valID = ValueID(type, useMC);
1164 if (valID >= 0 && valID < fValues.GetEntries()) {
1165 AliInfo(Form("Value '%s' is already created in slot #%d", AliRsnMiniValue::ValueName(type, useMC), valID));
1167 valID = fValues.GetEntries();
1168 AliInfo(Form("Creating value '%s' in slot #%d", AliRsnMiniValue::ValueName(type, useMC), valID));
1169 new (fValues[valID]) AliRsnMiniValue(type, useMC);
1175 //----------------------------------------------------------------------------------
1176 Int_t AliRsnMiniAnalysisTask::ValueID(AliRsnMiniValue::EType type, Bool_t useMC)
1179 // Searches if a value computation is initialized
1182 const char *name = AliRsnMiniValue::ValueName(type, useMC);
1183 TObject *obj = fValues.FindObject(name);
1185 return fValues.IndexOf(obj);
1190 //----------------------------------------------------------------------------------
1191 AliRsnMiniOutput *AliRsnMiniAnalysisTask::CreateOutput(const char *name, AliRsnMiniOutput::EOutputType type, AliRsnMiniOutput::EComputation src)
1194 // Create a new histogram definition in the task,
1195 // which is then returned to the user for its configuration
1198 Int_t n = fHistograms.GetEntries();
1199 AliRsnMiniOutput *newDef = new (fHistograms[n]) AliRsnMiniOutput(name, type, src);
1204 //----------------------------------------------------------------------------------
1205 AliRsnMiniOutput *AliRsnMiniAnalysisTask::CreateOutput(const char *name, const char *outType, const char *compType)
1208 // Create a new histogram definition in the task,
1209 // which is then returned to the user for its configuration
1212 Int_t n = fHistograms.GetEntries();
1213 AliRsnMiniOutput *newDef = new (fHistograms[n]) AliRsnMiniOutput(name, outType, compType);