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() :
48 fUseCentrality(kFALSE),
49 fCentralityType("QUALITY"),
50 fUseAOD049CentralityPatch(kFALSE),
51 fContinuousMix(kTRUE),
57 fHistograms("AliRsnMiniOutput", 0),
58 fValues("AliRsnMiniValue", 0),
60 fHAEventsVsMulti(0x0),
62 fHAEventMultiCent(0x0),
75 // Dummy constructor ALWAYS needed for I/O.
79 //__________________________________________________________________________________________________
80 AliRsnMiniAnalysisTask::AliRsnMiniAnalysisTask(const char *name, Bool_t useMC) :
81 AliAnalysisTaskSE(name),
84 fUseCentrality(kFALSE),
85 fCentralityType("QUALITY"),
86 fUseAOD049CentralityPatch(kFALSE),
87 fContinuousMix(kTRUE),
93 fHistograms("AliRsnMiniOutput", 0),
94 fValues("AliRsnMiniValue", 0),
96 fHAEventsVsMulti(0x0),
98 fHAEventMultiCent(0x0),
111 // Default constructor.
112 // Define input and output slots here (never in the dummy constructor)
113 // Input slot #0 works with a TChain - it is connected to the default input container
114 // Output slot #1 writes into a TH1 container
117 DefineOutput(1, TList::Class());
120 //__________________________________________________________________________________________________
121 AliRsnMiniAnalysisTask::AliRsnMiniAnalysisTask(const AliRsnMiniAnalysisTask ©) :
122 AliAnalysisTaskSE(copy),
125 fUseCentrality(copy.fUseCentrality),
126 fCentralityType(copy.fCentralityType),
127 fUseAOD049CentralityPatch(copy.fUseAOD049CentralityPatch),
128 fContinuousMix(copy.fContinuousMix),
130 fMaxDiffMult(copy.fMaxDiffMult),
131 fMaxDiffVz(copy.fMaxDiffVz),
132 fMaxDiffAngle(copy.fMaxDiffAngle),
134 fHistograms(copy.fHistograms),
135 fValues(copy.fValues),
137 fHAEventsVsMulti(0x0),
139 fHAEventMultiCent(0x0),
141 fEventCuts(copy.fEventCuts),
142 fTrackCuts(copy.fTrackCuts),
145 fTriggerAna(copy.fTriggerAna),
146 fESDtrackCuts(copy.fESDtrackCuts),
148 fBigOutput(copy.fBigOutput),
149 fMixPrintRefresh(copy.fMixPrintRefresh)
153 // Implemented as requested by C++ standards.
154 // Can be used in PROOF and by plugins.
158 //__________________________________________________________________________________________________
159 AliRsnMiniAnalysisTask &AliRsnMiniAnalysisTask::operator=(const AliRsnMiniAnalysisTask ©)
162 // Assignment operator.
163 // Implemented as requested by C++ standards.
164 // Can be used in PROOF and by plugins.
167 AliAnalysisTaskSE::operator=(copy);
170 fUseMC = copy.fUseMC;
171 fUseCentrality = copy.fUseCentrality;
172 fCentralityType = copy.fCentralityType;
173 fUseAOD049CentralityPatch = copy.fUseAOD049CentralityPatch;
174 fContinuousMix = copy.fContinuousMix;
176 fMaxDiffMult = copy.fMaxDiffMult;
177 fMaxDiffVz = copy.fMaxDiffVz;
178 fMaxDiffAngle = copy.fMaxDiffAngle;
179 fHistograms = copy.fHistograms;
180 fValues = copy.fValues;
181 fHEventStat = copy.fHEventStat;
182 fHAEventsVsMulti = copy.fHAEventsVsMulti;
183 fHAEventVz = copy.fHAEventVz;
184 fHAEventMultiCent = copy.fHAEventMultiCent;
185 fHAEventPlane = copy.fHAEventPlane;
186 fEventCuts = copy.fEventCuts;
187 fTrackCuts = copy.fTrackCuts;
188 fTriggerAna = copy.fTriggerAna;
189 fESDtrackCuts = copy.fESDtrackCuts;
190 fBigOutput = copy.fBigOutput;
191 fMixPrintRefresh = copy.fMixPrintRefresh;
195 //__________________________________________________________________________________________________
196 AliRsnMiniAnalysisTask::~AliRsnMiniAnalysisTask()
200 // Clean-up the output list, but not the histograms that are put inside
201 // (the list is owner and will clean-up these histograms). Protect in PROOF case.
205 if (fOutput && !AliAnalysisManager::GetAnalysisManager()->IsProofMode()) {
211 //__________________________________________________________________________________________________
212 Int_t AliRsnMiniAnalysisTask::AddTrackCuts(AliRsnCutSet *cuts)
215 // Add a new cut set for a new criterion for track selection.
216 // A user can add as many as he wants, and each one corresponds
217 // to one of the available bits in the AliRsnMiniParticle mask.
218 // The only check is the following: if a cut set with the same name
219 // as the argument is there, this is not added.
220 // Return value is the array position of this set.
223 TObject *obj = fTrackCuts.FindObject(cuts->GetName());
226 AliInfo(Form("A cut set named '%s' already exists", cuts->GetName()));
227 return fTrackCuts.IndexOf(obj);
229 fTrackCuts.AddLast(cuts);
230 return fTrackCuts.IndexOf(cuts);
234 //__________________________________________________________________________________________________
235 void AliRsnMiniAnalysisTask::UserCreateOutputObjects()
238 // Initialization of outputs.
239 // This is called once per worker node.
246 AliInfo(Form("Selected event characterization: %s (%s)", (fUseCentrality ? "centrality" : "multiplicity"), fCentralityType.Data()));
248 // initialize trigger analysis
249 if (fTriggerAna) delete fTriggerAna;
250 fTriggerAna = new AliTriggerAnalysis;
252 // initialize ESD quality cuts
253 if (fESDtrackCuts) delete fESDtrackCuts;
254 fESDtrackCuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2010();
256 // create list and set it as owner of its content (MANDATORY)
257 if (fBigOutput) OpenFile(1);
258 fOutput = new TList();
261 // initialize event statistics counter
262 fHEventStat = new TH1F("hEventStat", "Event statistics", 4, 0.0, 4.0);
263 fHEventStat->GetXaxis()->SetBinLabel(1, "CINT1B");
264 fHEventStat->GetXaxis()->SetBinLabel(2, "V0AND");
265 fHEventStat->GetXaxis()->SetBinLabel(3, "Candle");
266 fHEventStat->GetXaxis()->SetBinLabel(4, "Accepted");
267 fOutput->Add(fHEventStat);
270 fHAEventsVsMulti = new TH1F("hAEventsVsMulti", "Accepted events vs Centrality", 100, 0, 100.0);
272 fHAEventsVsMulti = new TH1F("hAEventsVsMulti", "Accepted events vs Multiplicity",1000, 0, 1000.0);
273 fOutput->Add(fHAEventsVsMulti);
275 if(fHAEventVz) fOutput->Add(fHAEventVz);
276 if(fHAEventMultiCent) fOutput->Add(fHAEventMultiCent);
277 if(fHAEventPlane) fOutput->Add(fHAEventPlane);
279 TIter next(&fTrackCuts);
281 while ((cs = (AliRsnCutSet *) next())) {
285 // create temporary tree for filtered events
286 if (fMiniEvent) delete fMiniEvent;
287 fEvBuffer = new TTree("EventBuffer", "Temporary buffer for mini events");
288 fEvBuffer->Branch("events", "AliRsnMiniEvent", &fMiniEvent);
290 // create one histogram per each stored definition (event histograms)
291 Int_t i, ndef = fHistograms.GetEntries();
292 AliRsnMiniOutput *def = 0x0;
293 for (i = 0; i < ndef; i++) {
294 def = (AliRsnMiniOutput *)fHistograms[i];
296 if (!def->Init(GetName(), fOutput)) {
297 AliError(Form("Def '%s': failed initialization", def->GetName()));
302 // post data for ALL output slots >0 here, to get at least an empty histogram
303 PostData(1, fOutput);
306 //__________________________________________________________________________________________________
307 void AliRsnMiniAnalysisTask::UserExec(Option_t *)
311 // In this case, it checks if the event is acceptable, and eventually
312 // creates the corresponding mini-event and stores it in the buffer.
313 // The real histogram filling is done at the end, in "FinishTaskOutput".
316 // increment event counter
319 // check current event
320 Char_t check = CheckCurrentEvent();
323 // setup PID response
324 AliAnalysisManager *man = AliAnalysisManager::GetAnalysisManager();
325 AliInputEventHandler *inputHandler = (AliInputEventHandler *)man->GetInputEventHandler();
326 fRsnEvent.SetPIDResponse(inputHandler->GetPIDResponse());
328 // fill a mini-event from current
329 // and skip this event if no tracks were accepted
330 FillMiniEvent(check);
332 // fill MC based histograms on mothers,
333 // which do need the original event
335 if (fRsnEvent.IsESD() && fMCEvent)
336 FillTrueMotherESD(fMiniEvent);
337 else if (fRsnEvent.IsAOD() && fRsnEvent.GetAODList())
338 FillTrueMotherAOD(fMiniEvent);
341 // if the event is not empty, store it
342 if (fMiniEvent->IsEmpty()) {
343 AliDebugClass(2, Form("Rejecting empty event #%d", fEvNum));
345 Int_t id = fEvBuffer->GetEntries();
346 AliDebugClass(2, Form("Adding event #%d with ID = %d", fEvNum, id));
347 fMiniEvent->ID() = id;
351 // post data for computed stuff
352 PostData(1, fOutput);
355 //__________________________________________________________________________________________________
356 void AliRsnMiniAnalysisTask::FinishTaskOutput()
359 // This function is called at the end of the loop on available events,
360 // and then the buffer will be full with all the corresponding mini-events,
361 // each one containing all tracks selected by each of the available track cuts.
362 // Here a loop is done on each of these events, and both single-event and mixing are computed
365 // security code: reassign the buffer to the mini-event cursor
366 fEvBuffer->SetBranchAddress("events", &fMiniEvent);
369 Int_t ievt, nEvents = (Int_t)fEvBuffer->GetEntries();
370 Int_t idef, nDefs = fHistograms.GetEntries();
371 Int_t imix, iloop, ifill;
372 AliRsnMiniOutput *def = 0x0;
373 AliRsnMiniOutput::EComputation compType;
375 Int_t printNum = fMixPrintRefresh;
377 if (nEvents>1e5) printNum=nEvents/100;
378 else if (nEvents>1e4) printNum=nEvents/10;
382 // loop on events, and for each one fill all outputs
383 // using the appropriate procedure depending on its type
384 // only mother-related histograms are filled in UserExec,
385 // since they require direct access to MC event
387 for (ievt = 0; ievt < nEvents; ievt++) {
389 fEvBuffer->GetEntry(ievt);
390 if (printNum&&(ievt%printNum==0)) {
391 AliInfo(Form("[%s] Std.Event %d/%d",GetName(), ievt,nEvents));
392 timer.Stop(); timer.Print(); fflush(stdout); timer.Start(kFALSE);
395 for (idef = 0; idef < nDefs; idef++) {
396 def = (AliRsnMiniOutput *)fHistograms[idef];
398 compType = def->GetComputation();
399 // execute computation in the appropriate way
401 case AliRsnMiniOutput::kEventOnly:
402 //AliDebugClass(1, Form("Event %d, def '%s': event-value histogram filling", ievt, def->GetName()));
404 def->FillEvent(fMiniEvent, &fValues);
406 case AliRsnMiniOutput::kTruePair:
407 //AliDebugClass(1, Form("Event %d, def '%s': true-pair histogram filling", ievt, def->GetName()));
408 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
410 case AliRsnMiniOutput::kTrackPair:
411 //AliDebugClass(1, Form("Event %d, def '%s': pair-value histogram filling", ievt, def->GetName()));
412 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
414 case AliRsnMiniOutput::kTrackPairRotated1:
415 //AliDebugClass(1, Form("Event %d, def '%s': rotated (1) background histogram filling", ievt, def->GetName()));
416 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
418 case AliRsnMiniOutput::kTrackPairRotated2:
419 //AliDebugClass(1, Form("Event %d, def '%s': rotated (2) background histogram filling", ievt, def->GetName()));
420 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
423 // other kinds are processed elsewhere
425 AliDebugClass(2, Form("Computation = %d", (Int_t)compType));
428 AliDebugClass(1, Form("Event %6d: def = '%15s' -- fills = %5d", ievt, def->GetName(), ifill));
432 // if no mixing is required, stop here and post the output
434 AliDebugClass(2, "Stopping here, since no mixing is required");
435 PostData(1, fOutput);
439 // initialize mixing counter
440 Int_t nmatched[nEvents];
441 TString *smatched = new TString[nEvents];
442 for (ievt = 0; ievt < nEvents; ievt++) {
443 smatched[ievt] = "|";
448 AliInfo(Form("[%s] Std.Event %d/%d",GetName(), nEvents,nEvents));
449 timer.Stop(); timer.Print(); timer.Start(); fflush(stdout);
451 // search for good matchings
452 for (ievt = 0; ievt < nEvents; ievt++) {
453 if (printNum&&(ievt%printNum==0)) {
454 AliInfo(Form("[%s] EventMixing searching %d/%d",GetName(),ievt,nEvents));
455 timer.Stop(); timer.Print(); timer.Start(kFALSE); fflush(stdout);
457 if (nmatched[ievt] >= fNMix) continue;
458 fEvBuffer->GetEntry(ievt);
459 AliRsnMiniEvent evMain(*fMiniEvent);
460 for (iloop = 1; iloop < nEvents; iloop++) {
462 if (imix >= nEvents) imix -= nEvents;
463 if (imix == ievt) continue;
465 fEvBuffer->GetEntry(imix);
466 // skip if events are not matched
467 if (!EventsMatch(&evMain, fMiniEvent)) continue;
468 // check that the array of good matches for mixed does not already contain main event
469 if (smatched[imix].Contains(Form("|%d|", ievt))) continue;
470 // check that the found good events has not enough matches already
471 if (nmatched[imix] >= fNMix) continue;
472 // add new mixing candidate
473 smatched[ievt].Append(Form("%d|", imix));
476 if (nmatched[ievt] >= fNMix) break;
478 AliDebugClass(1, Form("Matches for event %5d = %d [%s] (missing are declared above)", evMain.ID(), nmatched[ievt], smatched[ievt].Data()));
481 AliInfo(Form("[%s] EventMixing searching %d/%d",GetName(),nEvents,nEvents));
482 timer.Stop(); timer.Print(); fflush(stdout); timer.Start();
485 TObjArray *list = 0x0;
486 TObjString *os = 0x0;
487 for (ievt = 0; ievt < nEvents; ievt++) {
488 if (printNum&&(ievt%printNum==0)) {
489 AliInfo(Form("[%s] EventMixing %d/%d",GetName(),ievt,nEvents));
490 timer.Stop(); timer.Print(); timer.Start(kFALSE); fflush(stdout);
493 fEvBuffer->GetEntry(ievt);
494 AliRsnMiniEvent evMain(*fMiniEvent);
495 list = smatched[ievt].Tokenize("|");
496 TObjArrayIter next(list);
497 while ( (os = (TObjString *)next()) ) {
498 imix = os->GetString().Atoi();
499 fEvBuffer->GetEntry(imix);
500 for (idef = 0; idef < nDefs; idef++) {
501 def = (AliRsnMiniOutput *)fHistograms[idef];
503 if (!def->IsTrackPairMix()) continue;
504 ifill += def->FillPair(&evMain, fMiniEvent, &fValues, kTRUE);
505 if (!def->IsSymmetric()) {
506 AliDebugClass(2, "Reflecting non symmetric pair");
507 ifill += def->FillPair(fMiniEvent, &evMain, &fValues, kFALSE);
516 AliInfo(Form("[%s] EventMixing %d/%d",GetName(),nEvents,nEvents));
517 timer.Stop(); timer.Print(); fflush(stdout);
522 for (iloop = 1; iloop < nEvents; iloop++) {
524 // restart from beginning if reached last event
525 if (imix >= nEvents) imix -= nEvents;
526 // avoid to mix an event with itself
527 if (imix == ievt) continue;
528 // skip all events already mixed enough times
529 if (fNMixed[ievt] >= fNMix) break;
530 if (fNMixed[imix] >= fNMix) continue;
531 fEvBuffer->GetEntry(imix);
532 // skip if events are not matched
533 if (TMath::Abs(evMain.Vz() - fMiniEvent->Vz() ) > fMaxDiffVz ) continue;
534 if (TMath::Abs(evMain.Mult() - fMiniEvent->Mult() ) > fMaxDiffMult ) continue;
535 if (TMath::Abs(evMain.Angle() - fMiniEvent->Angle()) > fMaxDiffAngle) continue;
536 // found a match: increment counter for both events
537 AliDebugClass(1, Form("Event %d, def '%s': event mixing (%d with %d)", ievt, def->GetName(), ievt, imix));
541 ifill += def->FillPair(&evMain, fMiniEvent, &fValues);
542 // stop if mixed enough times
543 if (fNMixed[ievt] >= fNMix) break;
546 // print number of mixings done with each event
547 for (ievt = 0; ievt < nEvents; ievt++) {
548 AliDebugClass(2, Form("Event %6d: mixed %2d times", ievt, fNMixed[ievt]));
552 // post computed data
553 PostData(1, fOutput);
556 //__________________________________________________________________________________________________
557 void AliRsnMiniAnalysisTask::Terminate(Option_t *)
560 // Draw result to screen, or perform fitting, normalizations
561 // Called once at the end of the query
564 fOutput = dynamic_cast<TList *>(GetOutputData(1));
566 AliError("Could not retrieve TList fOutput");
571 //__________________________________________________________________________________________________
572 Char_t AliRsnMiniAnalysisTask::CheckCurrentEvent()
575 // This method checks if current event is OK for analysis.
576 // In case it is, the pointers of the local AliRsnEvent data member
577 // will point to it, in order to allow cut checking, otherwise the
578 // function exits with a failure message.
580 // ESD events must pass the physics selection, AOD are supposed to do.
582 // While checking the event, a histogram is filled to count the number
583 // of CINT1B, V0AND and CANDLE events, which are needed for normalization
585 // Return values can be:
586 // -- 'E' if the event is accepted and is ESD
587 // -- 'A' if the event is accepted and is AOD
588 // -- 0 if the event is not accepted
591 // string to sum messages
595 // exit points are provided in all cases an event is bad
596 // if this block is passed, an event can be rejected only
597 // if it does not pass the set of event cuts defined in the task
600 if (fInputEvent->InheritsFrom(AliESDEvent::Class())) {
603 // ESD specific check: Physics Selection
604 // --> if this is failed, the event is rejected
605 isSelected = (((AliInputEventHandler *)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))->IsEventSelected() & AliVEvent::kMB);
607 AliDebugClass(2, "Event does not pass physics selections");
608 fRsnEvent.SetRef(0x0);
609 fRsnEvent.SetRefMC(0x0);
612 // set reference to input
613 fRsnEvent.SetRef(fInputEvent);
614 // add MC if requested and available
617 fRsnEvent.SetRefMC(fMCEvent);
619 AliWarning("MC event requested but not available");
620 fRsnEvent.SetRefMC(0x0);
623 } else if (fInputEvent->InheritsFrom(AliAODEvent::Class())) {
626 // set reference to input
627 fRsnEvent.SetRef(fInputEvent);
628 // add MC if requested and available (it is in the same object)
630 fRsnEvent.SetRefMC(fInputEvent);
631 if (!fRsnEvent.GetAODList()) {
632 AliWarning("MC event requested but not available");
633 fRsnEvent.SetRefMC(0x0);
637 AliError(Form("Bad input event class: %s", fInputEvent->ClassName()));
638 // reset pointers in local AliRsnEvent object
639 fRsnEvent.SetRef(0x0);
640 fRsnEvent.SetRefMC(0x0);
644 // fill counter of accepted events
645 fHEventStat->Fill(0.1);
647 // check if it is V0AND
648 // --> uses a cast to AliESDEvent even if the input is an AliAODEvent
649 Bool_t v0A = fTriggerAna->IsOfflineTriggerFired((AliESDEvent *)fInputEvent, AliTriggerAnalysis::kV0A);
650 Bool_t v0C = fTriggerAna->IsOfflineTriggerFired((AliESDEvent *)fInputEvent, AliTriggerAnalysis::kV0C);
652 msg += " -- VOAND = YES";
653 fHEventStat->Fill(1.1);
655 msg += " -- VOAND = NO ";
659 // --> requires at least one good quality track with Pt > 0.5 and |eta| <= 0.8
660 Int_t iTrack, ntracksLoop = fInputEvent->GetNumberOfTracks();
661 Bool_t candle = kFALSE;
662 for (iTrack = 0; iTrack < ntracksLoop; iTrack++) {
663 AliVTrack *track = (AliVTrack *)fInputEvent->GetTrack(iTrack);
664 AliESDtrack *esdt = dynamic_cast<AliESDtrack *>(track);
665 AliAODTrack *aodt = dynamic_cast<AliAODTrack *>(track);
666 if (track->Pt() < 0.5) continue;
667 if(TMath::Abs(track->Eta()) > 0.8) continue;
668 if (esdt) if (!fESDtrackCuts->AcceptTrack(esdt)) continue;
669 if (aodt) if (!aodt->TestFilterBit(5)) continue;
674 msg += " -- CANDLE = YES";
675 fHEventStat->Fill(2.1);
677 msg += " -- CANDLE = NO ";
680 // if event cuts are defined, they are checked here
681 // final decision on the event depends on this
684 if (!fEventCuts->IsSelected(&fRsnEvent)) {
685 msg += " -- Local cuts = REJECTED";
688 msg += " -- Local cuts = ACCEPTED";
692 msg += " -- Local cuts = NONE";
696 // if the above exit point is not taken, the event is accepted
697 AliDebugClass(2, Form("Stats: %s", msg.Data()));
699 fHEventStat->Fill(3.1);
700 Double_t multi = ComputeCentrality((output == 'E'));
701 fHAEventsVsMulti->Fill(multi);
702 if(fHAEventVz) fHAEventVz->Fill(multi,fInputEvent->GetPrimaryVertex()->GetZ());
703 if(fHAEventMultiCent) fHAEventMultiCent->Fill(multi,ComputeMultiplicity(output == 'E',fHAEventMultiCent->GetYaxis()->GetTitle()));
704 if(fHAEventPlane) fHAEventPlane->Fill(multi,ComputeAngle());
711 //__________________________________________________________________________________________________
712 void AliRsnMiniAnalysisTask::FillMiniEvent(Char_t evType)
715 // Refresh cursor mini-event data member to fill with current event.
716 // Returns the total number of tracks selected.
719 // assign event-related values
720 if (fMiniEvent) delete fMiniEvent;
721 fMiniEvent = new AliRsnMiniEvent;
722 fMiniEvent->Vz() = fInputEvent->GetPrimaryVertex()->GetZ();
723 fMiniEvent->Angle() = ComputeAngle();
724 fMiniEvent->Mult() = ComputeCentrality((evType == 'E'));
725 AliDebugClass(2, Form("Event %d: type = %c -- vz = %f -- mult = %f -- angle = %f", fEvNum, evType, fMiniEvent->Vz(), fMiniEvent->Mult(), fMiniEvent->Angle()));
727 // loop on daughters and assign track-related values
728 Int_t ic, ncuts = fTrackCuts.GetEntries();
729 Int_t ip, npart = fRsnEvent.GetAbsoluteSum();
730 Int_t npos = 0, nneg = 0, nneu = 0;
731 AliRsnDaughter cursor;
732 AliRsnMiniParticle miniParticle;
733 for (ip = 0; ip < npart; ip++) {
734 // point cursor to next particle
735 fRsnEvent.SetDaughter(cursor, ip);
736 // copy momentum and MC info if present
737 miniParticle.CopyDaughter(&cursor);
738 miniParticle.Index() = ip;
739 // switch on the bits corresponding to passed cuts
740 for (ic = 0; ic < ncuts; ic++) {
741 AliRsnCutSet *cuts = (AliRsnCutSet *)fTrackCuts[ic];
742 if (cuts->IsSelected(&cursor)) miniParticle.SetCutBit(ic);
744 // if a track passes at least one track cut, it is added to the pool
745 if (miniParticle.CutBits()) {
746 fMiniEvent->AddParticle(miniParticle);
747 if (miniParticle.Charge() == '+') npos++;
748 else if (miniParticle.Charge() == '-') nneg++;
753 // get number of accepted tracks
754 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));
757 //__________________________________________________________________________________________________
758 Double_t AliRsnMiniAnalysisTask::ComputeAngle()
761 // Get the plane angle
764 AliEventplane *plane = 0x0;
766 if (fInputEvent->InheritsFrom(AliESDEvent::Class()))
767 plane = fInputEvent->GetEventplane();
768 else if (fInputEvent->InheritsFrom(AliAODEvent::Class())) {
769 AliAODEvent *aodEvent = (AliAODEvent *)fInputEvent;
770 plane = aodEvent->GetHeader()->GetEventplaneP();
774 return plane->GetEventplane("Q");
776 AliWarning("No event plane defined");
781 //__________________________________________________________________________________________________
782 Double_t AliRsnMiniAnalysisTask::ComputeCentrality(Bool_t isESD)
785 // Computes event centrality/multiplicity according to the criterion defined
786 // by two elements: (1) choice between multiplicity and centrality and
787 // (2) the string defining what criterion must be used for specific computation.
790 if (fUseCentrality) {
792 if ((!fUseMC) && (!isESD) && (fUseAOD049CentralityPatch)) {
793 return ApplyCentralityPatchAOD049();
795 AliCentrality *centrality = fInputEvent->GetCentrality();
797 AliError("Cannot compute centrality!");
800 return centrality->GetCentralityPercentile(fCentralityType.Data());
803 if (!fCentralityType.CompareTo("TRACKS"))
804 return fInputEvent->GetNumberOfTracks();
805 else if (!fCentralityType.CompareTo("QUALITY"))
807 return AliESDtrackCuts::GetReferenceMultiplicity((AliESDEvent *)fInputEvent, kTRUE);
810 Int_t iTrack, ntracksLoop = fInputEvent->GetNumberOfTracks();
811 for (iTrack = 0; iTrack < ntracksLoop; iTrack++) {
812 AliVTrack *track = (AliVTrack *)fInputEvent->GetTrack(iTrack);
813 AliAODTrack *aodt = dynamic_cast<AliAODTrack *>(track);
815 if (!aodt->TestFilterBit(5)) continue;
820 else if (!fCentralityType.CompareTo("TRACKLETS")) {
822 const AliMultiplicity *mult = ((AliESDEvent *)fInputEvent)->GetMultiplicity();
823 Float_t nClusters[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
824 for(Int_t ilay = 0; ilay < 6; ilay++) nClusters[ilay] = (Float_t)mult->GetNumberOfITSClusters(ilay);
825 return AliESDUtils::GetCorrSPD2(nClusters[1], fInputEvent->GetPrimaryVertex()->GetZ());
827 AliWarning("Cannot compute multiplicity with SPD tracklets from AOD");
831 AliError(Form("String '%s' does not define a possible multiplicity/centrality computation", fCentralityType.Data()));
837 //__________________________________________________________________________________________________
838 Double_t AliRsnMiniAnalysisTask::ComputeMultiplicity(Bool_t isESD,TString type)
841 // Computes event multiplicity according to the string defining
842 // what criterion must be used for specific computation.
847 if (!type.CompareTo("TRACKS"))
848 return fInputEvent->GetNumberOfTracks();
849 else if (!type.CompareTo("QUALITY"))
851 return AliESDtrackCuts::GetReferenceMultiplicity((AliESDEvent *)fInputEvent, kTRUE);
854 Int_t iTrack, ntracksLoop = fInputEvent->GetNumberOfTracks();
855 for (iTrack = 0; iTrack < ntracksLoop; iTrack++) {
856 AliVTrack *track = (AliVTrack *)fInputEvent->GetTrack(iTrack);
857 AliAODTrack *aodt = dynamic_cast<AliAODTrack *>(track);
859 if (!aodt->TestFilterBit(5)) continue;
864 else if (!type.CompareTo("TRACKLETS")) {
866 const AliMultiplicity *mult = ((AliESDEvent *)fInputEvent)->GetMultiplicity();
867 Float_t nClusters[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
868 for(Int_t ilay = 0; ilay < 6; ilay++) nClusters[ilay] = (Float_t)mult->GetNumberOfITSClusters(ilay);
869 return AliESDUtils::GetCorrSPD2(nClusters[1], fInputEvent->GetPrimaryVertex()->GetZ());
871 AliWarning("Cannot compute multiplicity with SPD tracklets from AOD");
875 AliError(Form("String '%s' does not define a possible multiplicity/centrality computation", type.Data()));
882 //__________________________________________________________________________________________________
883 void AliRsnMiniAnalysisTask::FillTrueMotherESD(AliRsnMiniEvent *miniEvent)
886 // Fills the histograms with true mother (ESD version)
890 Int_t id, ndef = fHistograms.GetEntries();
891 Int_t ip, label1, label2, npart = fMCEvent->GetNumberOfTracks();
892 static AliRsnMiniPair miniPair;
893 AliMCParticle *daughter1, *daughter2;
894 TLorentzVector p1, p2;
895 AliRsnMiniOutput *def = 0x0;
897 for (id = 0; id < ndef; id++) {
898 def = (AliRsnMiniOutput *)fHistograms[id];
900 if (!def->IsMother()) continue;
901 for (ip = 0; ip < npart; ip++) {
902 AliMCParticle *part = (AliMCParticle *)fMCEvent->GetTrack(ip);
903 if (part->Particle()->GetPdgCode() != def->GetMotherPDG()) continue;
904 // check that daughters match expected species
905 if (part->Particle()->GetNDaughters() < 2) continue;
906 label1 = part->Particle()->GetDaughter(0);
907 label2 = part->Particle()->GetDaughter(1);
908 daughter1 = (AliMCParticle *)fMCEvent->GetTrack(label1);
909 daughter2 = (AliMCParticle *)fMCEvent->GetTrack(label2);
911 if (TMath::Abs(daughter1->Particle()->GetPdgCode()) == def->GetPDG(0) && TMath::Abs(daughter2->Particle()->GetPdgCode()) == def->GetPDG(1)) {
913 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(0));
914 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(1));
915 } else if (TMath::Abs(daughter1->Particle()->GetPdgCode()) == def->GetPDG(1) && TMath::Abs(daughter2->Particle()->GetPdgCode()) == def->GetPDG(0)) {
917 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(1));
918 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(0));
920 if (!okMatch) continue;
921 // assign momenta to computation object
922 miniPair.Sum(0) = miniPair.Sum(1) = (p1 + p2);
923 miniPair.FillRef(def->GetMotherMass());
925 def->FillMother(&miniPair, miniEvent, &fValues);
930 //__________________________________________________________________________________________________
931 void AliRsnMiniAnalysisTask::FillTrueMotherAOD(AliRsnMiniEvent *miniEvent)
934 // Fills the histograms with true mother (AOD version)
938 TClonesArray *list = fRsnEvent.GetAODList();
939 Int_t id, ndef = fHistograms.GetEntries();
940 Int_t ip, label1, label2, npart = list->GetEntries();
941 static AliRsnMiniPair miniPair;
942 AliAODMCParticle *daughter1, *daughter2;
943 TLorentzVector p1, p2;
944 AliRsnMiniOutput *def = 0x0;
946 for (id = 0; id < ndef; id++) {
947 def = (AliRsnMiniOutput *)fHistograms[id];
949 if (!def->IsMother()) continue;
950 for (ip = 0; ip < npart; ip++) {
951 AliAODMCParticle *part = (AliAODMCParticle *)list->At(ip);
952 if (part->GetPdgCode() != def->GetMotherPDG()) continue;
953 // check that daughters match expected species
954 if (part->GetNDaughters() < 2) continue;
955 label1 = part->GetDaughter(0);
956 label2 = part->GetDaughter(1);
957 daughter1 = (AliAODMCParticle *)list->At(label1);
958 daughter2 = (AliAODMCParticle *)list->At(label2);
960 if (TMath::Abs(daughter1->GetPdgCode()) == def->GetPDG(0) && TMath::Abs(daughter2->GetPdgCode()) == def->GetPDG(1)) {
962 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(0));
963 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(1));
964 } else if (TMath::Abs(daughter1->GetPdgCode()) == def->GetPDG(1) && TMath::Abs(daughter2->GetPdgCode()) == def->GetPDG(0)) {
966 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(1));
967 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(0));
969 if (!okMatch) continue;
970 // assign momenta to computation object
971 miniPair.Sum(0) = miniPair.Sum(1) = (p1 + p2);
972 miniPair.FillRef(def->GetMotherMass());
974 def->FillMother(&miniPair, miniEvent, &fValues);
979 //__________________________________________________________________________________________________
980 Bool_t AliRsnMiniAnalysisTask::EventsMatch(AliRsnMiniEvent *event1, AliRsnMiniEvent *event2)
983 // Check if two events are compatible.
984 // If the mixing is continuous, this is true if differences in vz, mult and angle are smaller than
985 // the specified values.
986 // If the mixing is binned, this is true if the events are in the same bin.
989 if (!event1 || !event2) return kFALSE;
990 Int_t ivz1, ivz2, imult1, imult2, iangle1, iangle2;
993 if (fContinuousMix) {
994 dv = TMath::Abs(event1->Vz() - event2->Vz() );
995 dm = TMath::Abs(event1->Mult() - event2->Mult() );
996 da = TMath::Abs(event1->Angle() - event2->Angle());
997 if (dv > fMaxDiffVz) {
998 //AliDebugClass(2, Form("Events #%4d and #%4d don't match due to a too large diff in Vz = %f", event1->ID(), event2->ID(), dv));
1001 if (dm > fMaxDiffMult ) {
1002 //AliDebugClass(2, Form("Events #%4d and #%4d don't match due to a too large diff in Mult = %f", event1->ID(), event2->ID(), dm));
1005 if (da > fMaxDiffAngle) {
1006 //AliDebugClass(2, Form("Events #%4d and #%4d don't match due to a too large diff in Angle = %f", event1->ID(), event2->ID(), da));
1011 ivz1 = (Int_t)(event1->Vz() / fMaxDiffVz);
1012 ivz2 = (Int_t)(event2->Vz() / fMaxDiffVz);
1013 imult1 = (Int_t)(event1->Mult() / fMaxDiffMult);
1014 imult2 = (Int_t)(event2->Mult() / fMaxDiffMult);
1015 iangle1 = (Int_t)(event1->Angle() / fMaxDiffAngle);
1016 iangle2 = (Int_t)(event2->Angle() / fMaxDiffAngle);
1017 if (ivz1 != ivz2) return kFALSE;
1018 if (imult1 != imult2) return kFALSE;
1019 if (iangle1 != iangle2) return kFALSE;
1025 //---------------------------------------------------------------------
1026 Double_t AliRsnMiniAnalysisTask::ApplyCentralityPatchAOD049()
1029 //Apply centrality patch for AOD049 outliers
1031 if (fInputEvent->InheritsFrom(AliESDEvent::Class())) {
1032 AliWarning("Requested patch for AOD049 for ESD. ");
1036 if (fCentralityType!="V0M") {
1037 AliWarning("Requested patch forAOD049 for wrong value (not centrality from V0).");
1041 AliCentrality *centrality = fInputEvent->GetCentrality();
1043 AliWarning("Cannot get centrality from AOD event.");
1047 Float_t cent = (Float_t)(centrality->GetCentralityPercentile("V0M"));
1049 Bool_t isSelRun = kFALSE;
1050 Int_t selRun[5] = {138364, 138826, 138828, 138836, 138871};
1052 Int_t quality = centrality->GetQuality();
1054 cent=(Float_t)centrality->GetCentralityPercentileUnchecked("V0M");
1056 Int_t runnum=aodEvent->GetRunNumber();
1057 for(Int_t ir=0;ir<5;ir++){
1058 if(runnum==selRun[ir]){
1063 if((quality==8||quality==9)&&isSelRun) cent=(Float_t)centrality->GetCentralityPercentileUnchecked("V0M");
1070 AliAODEvent *aodEvent = (AliAODEvent *)fInputEvent;
1071 AliAODVZERO *aodV0 = (AliAODVZERO *) aodEvent->GetVZEROData();
1072 v0+=aodV0->GetMTotV0A();
1073 v0+=aodV0->GetMTotV0C();
1074 if ( (cent==0) && (v0<19500) ) {
1075 AliDebug(3, Form("Filtering issue in centrality -> cent = %5.2f",cent));
1078 Float_t tkl = (Float_t)(aodEvent->GetTracklets()->GetNumberOfTracklets());
1079 Float_t val = 1.30552 + 0.147931 * v0;
1081 Float_t tklSigma[101] = {176.644, 156.401, 153.789, 153.015, 142.476, 137.951, 136.127, 129.852, 127.436, 124.86,
1082 120.788, 115.611, 113.172, 110.496, 109.127, 104.421, 102.479, 99.9766, 97.5152, 94.0654,
1083 92.4602, 89.3364, 87.1342, 83.3497, 82.6216, 81.1084, 78.0793, 76.1234, 72.9434, 72.1334,
1084 68.0056, 68.2755, 66.0376, 62.9666, 62.4274, 59.65, 58.3776, 56.6361, 54.5184, 53.4224,
1085 51.932, 50.8922, 48.2848, 47.912, 46.5717, 43.4114, 43.2083, 41.3065, 40.1863, 38.5255,
1086 37.2851, 37.5396, 34.4949, 33.8366, 31.8043, 31.7412, 30.8392, 30.0274, 28.8793, 27.6398,
1087 26.6488, 25.0183, 25.1489, 24.4185, 22.9107, 21.2002, 21.6977, 20.1242, 20.4963, 19.0235,
1088 19.298, 17.4103, 16.868, 15.2939, 15.2939, 16.0295, 14.186, 14.186, 15.2173, 12.9504, 12.9504,
1089 12.9504, 15.264, 12.3674, 12.3674, 12.3674, 12.3674, 12.3674, 18.3811, 13.7544, 13.7544,
1090 13.7544, 13.7544, 13.7544, 13.7544, 13.7544, 13.7544, 13.7544, 13.7544, 13.7544, 13.7544
1093 if ( TMath::Abs(tkl-val) > 6.*tklSigma[(Int_t)cent] ) {
1094 AliDebug(3, Form("Outlier event in centrality -> cent = %5.2f",cent));
1098 //force it to be -999. whatever the negative value was
1104 //----------------------------------------------------------------------------------
1105 void AliRsnMiniAnalysisTask::SetEventQAHist(TString type,TH2F* histo)
1108 AliWarning(Form("event QA histogram pointer not defined for slot %s",type.Data()));
1114 if(!type.CompareTo("vz")) fHAEventVz = histo;
1115 else if(!type.CompareTo("multicent")){
1116 TString mtype(histo->GetYaxis()->GetTitle());
1118 if(mtype.CompareTo("QUALITY") && mtype.CompareTo("TRACKS") && mtype.CompareTo("TRACKLETS")){
1119 AliWarning(Form("multiplicity vs. centrality histogram y-axis %s unknown, setting to TRACKS",mtype.Data()));
1120 histo->GetYaxis()->SetTitle("TRACKS");
1122 fHAEventMultiCent = histo;
1124 else if(!type.CompareTo("eventplane")) fHAEventPlane = histo;
1125 else AliWarning(Form("event QA histogram slot %s undefined",type.Data()));