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>
20 #include "AliEventplane.h"
21 #include "AliMultiplicity.h"
22 #include "AliTriggerAnalysis.h"
23 #include "AliAnalysisManager.h"
24 #include "AliInputEventHandler.h"
26 #include "AliESDtrackCuts.h"
27 #include "AliESDUtils.h"
29 #include "AliAODEvent.h"
30 #include "AliAODMCParticle.h"
32 #include "AliRsnCutSet.h"
33 #include "AliRsnMiniPair.h"
34 #include "AliRsnMiniEvent.h"
35 #include "AliRsnMiniParticle.h"
37 #include "AliRsnMiniAnalysisTask.h"
39 ClassImp(AliRsnMiniAnalysisTask)
41 //__________________________________________________________________________________________________
42 AliRsnMiniAnalysisTask::AliRsnMiniAnalysisTask() :
46 fUseCentrality(kFALSE),
47 fCentralityType("QUALITY"),
48 fContinuousMix(kTRUE),
54 fHistograms("AliRsnMiniOutput", 0),
55 fValues("AliRsnMiniValue", 0),
67 // Dummy constructor ALWAYS needed for I/O.
71 //__________________________________________________________________________________________________
72 AliRsnMiniAnalysisTask::AliRsnMiniAnalysisTask(const char *name, Bool_t useMC) :
73 AliAnalysisTaskSE(name),
76 fUseCentrality(kFALSE),
77 fCentralityType("QUALITY"),
78 fContinuousMix(kTRUE),
84 fHistograms("AliRsnMiniOutput", 0),
85 fValues("AliRsnMiniValue", 0),
97 // Default constructor.
98 // Define input and output slots here (never in the dummy constructor)
99 // Input slot #0 works with a TChain - it is connected to the default input container
100 // Output slot #1 writes into a TH1 container
103 DefineOutput(1, TList::Class());
106 //__________________________________________________________________________________________________
107 AliRsnMiniAnalysisTask::AliRsnMiniAnalysisTask(const AliRsnMiniAnalysisTask& copy) :
108 AliAnalysisTaskSE(copy),
111 fUseCentrality(copy.fUseCentrality),
112 fCentralityType(copy.fCentralityType),
113 fContinuousMix(copy.fContinuousMix),
115 fMaxDiffMult(copy.fMaxDiffMult),
116 fMaxDiffVz(copy.fMaxDiffVz),
117 fMaxDiffAngle(copy.fMaxDiffAngle),
119 fHistograms(copy.fHistograms),
120 fValues(copy.fValues),
122 fEventCuts(copy.fEventCuts),
123 fTrackCuts(copy.fTrackCuts),
126 fTriggerAna(copy.fTriggerAna),
127 fESDtrackCuts(copy.fESDtrackCuts),
129 fBigOutput(copy.fBigOutput)
133 // Implemented as requested by C++ standards.
134 // Can be used in PROOF and by plugins.
138 //__________________________________________________________________________________________________
139 AliRsnMiniAnalysisTask& AliRsnMiniAnalysisTask::operator=(const AliRsnMiniAnalysisTask& copy)
142 // Assignment operator.
143 // Implemented as requested by C++ standards.
144 // Can be used in PROOF and by plugins.
147 AliAnalysisTaskSE::operator=(copy);
149 fUseMC = copy.fUseMC;
150 fUseCentrality = copy.fUseCentrality;
151 fCentralityType = copy.fCentralityType;
152 fContinuousMix = copy.fContinuousMix;
154 fMaxDiffMult = copy.fMaxDiffMult;
155 fMaxDiffVz = copy.fMaxDiffVz;
156 fMaxDiffAngle = copy.fMaxDiffAngle;
157 fHistograms = copy.fHistograms;
158 fValues = copy.fValues;
159 fEventCuts = copy.fEventCuts;
160 fTrackCuts = copy.fTrackCuts;
161 fTriggerAna = copy.fTriggerAna;
162 fESDtrackCuts = copy.fESDtrackCuts;
163 fBigOutput = copy.fBigOutput;
168 //__________________________________________________________________________________________________
169 AliRsnMiniAnalysisTask::~AliRsnMiniAnalysisTask()
173 // Clean-up the output list, but not the histograms that are put inside
174 // (the list is owner and will clean-up these histograms). Protect in PROOF case.
178 if (fOutput && !AliAnalysisManager::GetAnalysisManager()->IsProofMode()) {
184 //__________________________________________________________________________________________________
185 Int_t AliRsnMiniAnalysisTask::AddTrackCuts(AliRsnCutSet *cuts)
188 // Add a new cut set for a new criterion for track selection.
189 // A user can add as many as he wants, and each one corresponds
190 // to one of the available bits in the AliRsnMiniParticle mask.
191 // The only check is the following: if a cut set with the same name
192 // as the argument is there, this is not added.
193 // Return value is the array position of this set.
196 TObject *obj = fTrackCuts.FindObject(cuts->GetName());
199 AliInfo(Form("A cut set named '%s' already exists", cuts->GetName()));
200 return fTrackCuts.IndexOf(obj);
202 fTrackCuts.AddLast(cuts);
203 return fTrackCuts.IndexOf(cuts);
207 //__________________________________________________________________________________________________
208 void AliRsnMiniAnalysisTask::UserCreateOutputObjects()
211 // Initialization of outputs.
212 // This is called once per worker node.
219 AliInfo(Form("Selected event characterization: %s (%s)", (fUseCentrality ? "centrality" : "multiplicity"), fCentralityType.Data()));
221 // initialize trigger analysis
222 if (fTriggerAna) delete fTriggerAna;
223 fTriggerAna = new AliTriggerAnalysis;
225 // initialize ESD quality cuts
226 if (fESDtrackCuts) delete fESDtrackCuts;
227 fESDtrackCuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2010();
229 // create list and set it as owner of its content (MANDATORY)
230 if (fBigOutput) OpenFile(1);
231 fOutput = new TList();
234 // initialize event statistics counter
235 fHEventStat = new TH1F("hEventStat", "Event statistics", 4, 0.0, 4.0);
236 fHEventStat->GetXaxis()->SetBinLabel(1, "CINT1B");
237 fHEventStat->GetXaxis()->SetBinLabel(2, "V0AND");
238 fHEventStat->GetXaxis()->SetBinLabel(3, "Candle");
239 fHEventStat->GetXaxis()->SetBinLabel(4, "Accepted");
240 fOutput->Add(fHEventStat);
242 // create temporary tree for filtered events
243 if (fMiniEvent) delete fMiniEvent;
244 fEvBuffer = new TTree("EventBuffer", "Temporary buffer for mini events");
245 fEvBuffer->Branch("events", "AliRsnMiniEvent", &fMiniEvent);
247 // create one histogram per each stored definition (event histograms)
248 Int_t i, ndef = fHistograms.GetEntries();
249 AliRsnMiniOutput *def = 0x0;
250 for (i = 0; i < ndef; i++) {
251 def = (AliRsnMiniOutput*)fHistograms[i];
253 if (!def->Init(GetName(), fOutput)) {
254 AliError(Form("Def '%s': failed initialization", def->GetName()));
259 // post data for ALL output slots >0 here, to get at least an empty histogram
260 PostData(1, fOutput);
263 //__________________________________________________________________________________________________
264 void AliRsnMiniAnalysisTask::UserExec(Option_t *)
268 // In this case, it checks if the event is acceptable, and eventually
269 // creates the corresponding mini-event and stores it in the buffer.
270 // The real histogram filling is done at the end, in "FinishTaskOutput".
276 // check current event
277 Char_t check = CheckCurrentEvent();
280 // setup PID response
281 AliAnalysisManager *man = AliAnalysisManager::GetAnalysisManager();
282 AliInputEventHandler *inputHandler = (AliInputEventHandler*)man->GetInputEventHandler();
283 fRsnEvent.SetPIDResponse(inputHandler->GetPIDResponse());
285 // fill a mini-event from current
286 // and skip this event if no tracks were accepted
287 FillMiniEvent(check);
289 // fill MC based histograms on mothers,
290 // which do need the original event
292 if (fRsnEvent.IsESD() && fMCEvent)
293 FillTrueMotherESD(fMiniEvent);
294 else if (fRsnEvent.IsAOD() && fRsnEvent.GetAODList())
295 FillTrueMotherAOD(fMiniEvent);
301 // post data for computed stuff
302 PostData(1, fOutput);
305 //__________________________________________________________________________________________________
306 void AliRsnMiniAnalysisTask::FinishTaskOutput()
309 // This function is called at the end of the loop on available events,
310 // and then the buffer will be full with all the corresponding mini-events,
311 // each one containing all tracks selected by each of the available track cuts.
312 // Here a loop is done on each of these events, and both single-event and mixing are computed
315 // security code: reassign the buffer to the mini-event cursor
316 fEvBuffer->SetBranchAddress("events", &fMiniEvent);
319 Int_t ievt, nEvents = (Int_t)fEvBuffer->GetEntries();
320 Int_t idef, nDefs = fHistograms.GetEntries();
321 Int_t imix, iloop, ifill;
322 AliRsnMiniOutput *def = 0x0;
323 AliRsnMiniOutput::EComputation compType;
325 // loop on events, and for each one fill all outputs
326 // using the appropriate procedure depending on its type
327 // only mother-related histograms are filled in UserExec,
328 // since they require direct access to MC event
329 for (ievt = 0; ievt < nEvents; ievt++) {
331 fEvBuffer->GetEntry(ievt);
333 for (idef = 0; idef < nDefs; idef++) {
334 def = (AliRsnMiniOutput*)fHistograms[idef];
336 compType = def->GetComputation();
337 // execute computation in the appropriate way
339 case AliRsnMiniOutput::kEventOnly:
340 AliDebugClass(1, Form("Event %d, def '%s': event-value histogram filling", ievt, def->GetName()));
342 def->FillEvent(fMiniEvent, &fValues);
344 case AliRsnMiniOutput::kTruePair:
345 AliDebugClass(1, Form("Event %d, def '%s': true-pair histogram filling", ievt, def->GetName()));
346 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
348 case AliRsnMiniOutput::kTrackPair:
349 AliDebugClass(1, Form("Event %d, def '%s': pair-value histogram filling", ievt, def->GetName()));
350 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
352 case AliRsnMiniOutput::kTrackPairRotated1:
353 AliDebugClass(1, Form("Event %d, def '%s': rotated (1) background histogram filling", ievt, def->GetName()));
354 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
356 case AliRsnMiniOutput::kTrackPairRotated2:
357 AliDebugClass(1, Form("Event %d, def '%s': rotated (2) background histogram filling", ievt, def->GetName()));
358 ifill = def->FillPair(fMiniEvent, fMiniEvent, &fValues);
361 // other kinds are processed elsewhere
363 AliDebugClass(2, Form("Computation = %d", (Int_t)compType));
366 AliDebugClass(1, Form("Event %6d: def = '%15s' -- fills = %5d", ievt, def->GetName(), ifill));
370 // if no mixing is required, stop here and post the output
372 AliDebugClass(2, "Stopping here, since no mixing is required");
373 PostData(1, fOutput);
377 // initialize mixing counter
378 TString *matched = new TString[nEvents];
379 for (ievt = 0; ievt < nEvents; ievt++) {
383 // search for good matchings
384 for (ievt = 0; ievt < nEvents; ievt++) {
386 fEvBuffer->GetEntry(ievt);
387 AliRsnMiniEvent evMain(*fMiniEvent);
388 for (iloop = 1; iloop < nEvents; iloop++) {
390 if (imix >= nEvents) imix -= nEvents;
391 if (imix == ievt) continue;
393 fEvBuffer->GetEntry(imix);
394 // skip if events are not matched
395 if (!EventsMatch(&evMain, fMiniEvent)) continue;
396 // check that the array of good matches for mixed does not already contain main event
397 if (matched[imix].Contains(Form("|%d|", ievt))) continue;
398 // add new mixing candidate
399 matched[ievt].Append(Form("%d|", imix));
401 if (ifill >= fNMix) break;
403 AliDebugClass(1, Form("Matches for event %5d = %s", ievt, matched[ievt].Data()));
407 TObjArray *list = 0x0;
408 TObjString *os = 0x0;
409 for (ievt = 0; ievt < nEvents; ievt++) {
411 fEvBuffer->GetEntry(ievt);
412 AliRsnMiniEvent evMain(*fMiniEvent);
413 list = matched[ievt].Tokenize("|");
414 TObjArrayIter next(list);
415 while ( (os = (TObjString*)next()) ) {
416 imix = os->GetString().Atoi();
417 fEvBuffer->GetEntry(imix);
418 for (idef = 0; idef < nDefs; idef++) {
419 def = (AliRsnMiniOutput*)fHistograms[idef];
421 if (!def->IsTrackPairMix()) continue;
422 ifill += def->FillPair(&evMain, fMiniEvent, &fValues, kTRUE);
423 if (!def->IsSymmetric()) ifill += def->FillPair(fMiniEvent, &evMain, &fValues, kFALSE);
434 for (iloop = 1; iloop < nEvents; iloop++) {
436 // restart from beginning if reached last event
437 if (imix >= nEvents) imix -= nEvents;
438 // avoid to mix an event with itself
439 if (imix == ievt) continue;
440 // skip all events already mixed enough times
441 if (fNMixed[ievt] >= fNMix) break;
442 if (fNMixed[imix] >= fNMix) continue;
443 fEvBuffer->GetEntry(imix);
444 // skip if events are not matched
445 if (TMath::Abs(evMain.Vz() - fMiniEvent->Vz() ) > fMaxDiffVz ) continue;
446 if (TMath::Abs(evMain.Mult() - fMiniEvent->Mult() ) > fMaxDiffMult ) continue;
447 if (TMath::Abs(evMain.Angle() - fMiniEvent->Angle()) > fMaxDiffAngle) continue;
448 // found a match: increment counter for both events
449 AliDebugClass(1, Form("Event %d, def '%s': event mixing (%d with %d)", ievt, def->GetName(), ievt, imix));
453 ifill += def->FillPair(&evMain, fMiniEvent, &fValues);
454 // stop if mixed enough times
455 if (fNMixed[ievt] >= fNMix) break;
458 // print number of mixings done with each event
459 for (ievt = 0; ievt < nEvents; ievt++) {
460 AliDebugClass(2, Form("Event %6d: mixed %2d times", ievt, fNMixed[ievt]));
464 // post computed data
465 PostData(1, fOutput);
468 //__________________________________________________________________________________________________
469 void AliRsnMiniAnalysisTask::Terminate(Option_t *)
472 // Draw result to screen, or perform fitting, normalizations
473 // Called once at the end of the query
476 fOutput = dynamic_cast<TList*>(GetOutputData(1));
478 AliError("Could not retrieve TList fOutput");
483 //__________________________________________________________________________________________________
484 Char_t AliRsnMiniAnalysisTask::CheckCurrentEvent()
487 // This method checks if current event is OK for analysis.
488 // In case it is, the pointers of the local AliRsnEvent data member
489 // will point to it, in order to allow cut checking, otherwise the
490 // function exits with a failure message.
492 // ESD events must pass the physics selection, AOD are supposed to do.
494 // While checking the event, a histogram is filled to count the number
495 // of CINT1B, V0AND and CANDLE events, which are needed for normalization
497 // Return values can be:
498 // -- 'E' if the event is accepted and is ESD
499 // -- 'A' if the event is accepted and is AOD
500 // -- 0 if the event is not accepted
503 // string to sum messages
507 // exit points are provided in all cases an event is bad
508 // if this block is passed, an event can be rejected only
509 // if it does not pass the set of event cuts defined in the task
512 if (fInputEvent->InheritsFrom(AliESDEvent::Class())) {
515 // ESD specific check: Physics Selection
516 // --> if this is failed, the event is rejected
517 isSelected = (((AliInputEventHandler*)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))->IsEventSelected() & AliVEvent::kMB);
519 AliDebugClass(2, "Event does not pass physics selections");
520 fRsnEvent.SetRef(0x0);
521 fRsnEvent.SetRefMC(0x0);
524 // set reference to input
525 fRsnEvent.SetRef(fInputEvent);
526 // add MC if requested and available
529 fRsnEvent.SetRefMC(fMCEvent);
531 AliWarning("MC event requested but not available");
532 fRsnEvent.SetRefMC(0x0);
535 } else if (fInputEvent->InheritsFrom(AliAODEvent::Class())) {
538 // set reference to input
539 fRsnEvent.SetRef(fInputEvent);
540 // add MC if requested and available (it is in the same object)
542 fRsnEvent.SetRefMC(fInputEvent);
543 if (!fRsnEvent.GetAODList()) {
544 AliWarning("MC event requested but not available");
545 fRsnEvent.SetRefMC(0x0);
549 AliError(Form("Bad input event class: %s", fInputEvent->ClassName()));
550 // reset pointers in local AliRsnEvent object
551 fRsnEvent.SetRef(0x0);
552 fRsnEvent.SetRefMC(0x0);
556 // fill counter of accepted events
557 fHEventStat->Fill(0.1);
559 // check if it is V0AND
560 // --> uses a cast to AliESDEvent even if the input is an AliAODEvent
561 Bool_t v0A = fTriggerAna->IsOfflineTriggerFired((AliESDEvent*)fInputEvent, AliTriggerAnalysis::kV0A);
562 Bool_t v0C = fTriggerAna->IsOfflineTriggerFired((AliESDEvent*)fInputEvent, AliTriggerAnalysis::kV0C);
564 msg += " -- VOAND = YES";
565 fHEventStat->Fill(1.1);
567 msg += " -- VOAND = NO ";
571 // --> requires at least one good quality track with Pt > 0.5 and |eta| <= 0.8
572 Int_t iTrack, ntracksLoop = fInputEvent->GetNumberOfTracks();
573 Bool_t candle = kFALSE;
574 for (iTrack = 0; iTrack < ntracksLoop; iTrack++) {
575 AliVTrack *track = (AliVTrack*)fInputEvent->GetTrack(iTrack);
576 AliESDtrack *esdt = dynamic_cast<AliESDtrack*>(track);
577 AliAODTrack *aodt = dynamic_cast<AliAODTrack*>(track);
578 if (track->Pt() < 0.5) continue;
579 if(TMath::Abs(track->Eta()) > 0.8) continue;
580 if (esdt) if (!fESDtrackCuts->AcceptTrack(esdt)) continue;
581 if (aodt) if (!aodt->TestFilterBit(5)) continue;
586 msg += " -- CANDLE = YES";
587 fHEventStat->Fill(2.1);
589 msg += " -- CANDLE = NO ";
592 // if event cuts are defined, they are checked here
593 // final decision on the event depends on this
596 if (!fEventCuts->IsSelected(&fRsnEvent)) {
597 msg += " -- Local cuts = REJECTED";
600 msg += " -- Local cuts = ACCEPTED";
604 msg += " -- Local cuts = NONE";
608 // if the above exit point is not taken, the event is accepted
609 AliDebugClass(2, Form("Stats for event %d: %s", fEvNum, msg.Data()));
611 fHEventStat->Fill(3.1);
618 //__________________________________________________________________________________________________
619 void AliRsnMiniAnalysisTask::FillMiniEvent(Char_t evType)
622 // Refresh cursor mini-event data member to fill with current event.
623 // Returns the total number of tracks selected.
626 // assign event-related values
627 if (fMiniEvent) delete fMiniEvent;
628 fMiniEvent = new AliRsnMiniEvent;
629 fMiniEvent->ID() = fEvNum;
630 fMiniEvent->Vz() = fInputEvent->GetPrimaryVertex()->GetZ();
631 fMiniEvent->Angle() = ComputeAngle();
632 fMiniEvent->Mult() = ComputeCentrality((evType == 'E'));
633 AliDebugClass(2, Form("Event %d: type = %c -- vz = %f -- mult = %f -- angle = %f", fEvNum, evType, fMiniEvent->Vz(), fMiniEvent->Mult(), fMiniEvent->Angle()));
635 // loop on daughters and assign track-related values
636 Int_t ic, ncuts = fTrackCuts.GetEntries();
637 Int_t ip, npart = fRsnEvent.GetAbsoluteSum();
638 Int_t npos = 0, nneg = 0, nneu = 0;
639 AliRsnDaughter cursor;
640 AliRsnMiniParticle miniParticle;
641 for (ip = 0; ip < npart; ip++) {
642 // point cursor to next particle
643 fRsnEvent.SetDaughter(cursor, ip);
644 // copy momentum and MC info if present
645 miniParticle.CopyDaughter(&cursor);
646 miniParticle.Index() = ip;
647 // switch on the bits corresponding to passed cuts
648 for (ic = 0; ic < ncuts; ic++) {
649 AliRsnCutSet *cuts = (AliRsnCutSet*)fTrackCuts[ic];
650 if (cuts->IsSelected(&cursor)) miniParticle.SetCutBit(ic);
652 // if a track passes at least one track cut, it is added to the pool
653 if (miniParticle.CutBits()) {
654 fMiniEvent->AddParticle(miniParticle);
655 if (miniParticle.Charge() == '+') npos++;
656 else if (miniParticle.Charge() == '-') nneg++;
661 // get number of accepted tracks
662 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));
665 //__________________________________________________________________________________________________
666 Double_t AliRsnMiniAnalysisTask::ComputeAngle()
669 // Get the plane angle
672 AliEventplane *plane = 0x0;
674 if (fInputEvent->InheritsFrom(AliESDEvent::Class()))
675 plane = fInputEvent->GetEventplane();
676 else if (fInputEvent->InheritsFrom(AliAODEvent::Class())) {
677 AliAODEvent *aodEvent = (AliAODEvent*)fInputEvent;
678 plane = aodEvent->GetHeader()->GetEventplaneP();
682 return plane->GetEventplane("Q");
684 AliWarning("No event plane defined");
689 //__________________________________________________________________________________________________
690 Double_t AliRsnMiniAnalysisTask::ComputeCentrality(Bool_t isESD)
693 // Computes event centrality/multiplicity according to the criterion defined
694 // by two elements: (1) choice between multiplicity and centrality and
695 // (2) the string defining what criterion must be used for specific computation.
698 if (fUseCentrality) {
699 AliCentrality *centrality = fInputEvent->GetCentrality();
701 AliError("Cannot compute centrality!");
704 return centrality->GetCentralityPercentile(fCentralityType.Data());
706 if (!fCentralityType.CompareTo("TRACKS"))
707 return fInputEvent->GetNumberOfTracks();
708 else if (!fCentralityType.CompareTo("QUALITY"))
710 return AliESDtrackCuts::GetReferenceMultiplicity((AliESDEvent*)fInputEvent, kTRUE);
713 Int_t iTrack, ntracksLoop = fInputEvent->GetNumberOfTracks();
714 for (iTrack = 0; iTrack < ntracksLoop; iTrack++) {
715 AliVTrack *track = (AliVTrack*)fInputEvent->GetTrack(iTrack);
716 AliAODTrack *aodt = dynamic_cast<AliAODTrack*>(track);
718 if (!aodt->TestFilterBit(5)) continue;
723 else if (!fCentralityType.CompareTo("TRACKLETS")) {
725 const AliMultiplicity *mult = ((AliESDEvent*)fInputEvent)->GetMultiplicity();
726 Float_t nClusters[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
727 for(Int_t ilay = 0; ilay < 6; ilay++) nClusters[ilay] = (Float_t)mult->GetNumberOfITSClusters(ilay);
728 return AliESDUtils::GetCorrSPD2(nClusters[1], fInputEvent->GetPrimaryVertex()->GetZ());
730 AliWarning("Cannot compute multiplicity with SPD tracklets from AOD");
734 AliError(Form("String '%s' does not define a possible multiplicity/centrality computation", fCentralityType.Data()));
740 //__________________________________________________________________________________________________
741 void AliRsnMiniAnalysisTask::FillTrueMotherESD(AliRsnMiniEvent *miniEvent)
744 // Fills the histograms with true mother (ESD version)
748 Int_t id, ndef = fHistograms.GetEntries();
749 Int_t ip, label1, label2, npart = fMCEvent->GetNumberOfTracks();
750 static AliRsnMiniPair miniPair;
751 AliMCParticle *daughter1, *daughter2;
752 TLorentzVector p1, p2;
753 AliRsnMiniOutput *def = 0x0;
755 for (id = 0; id < ndef; id++) {
756 def = (AliRsnMiniOutput*)fHistograms[id];
758 if (!def->IsMother()) continue;
759 for (ip = 0; ip < npart; ip++) {
760 AliMCParticle *part = (AliMCParticle*)fMCEvent->GetTrack(ip);
761 if (part->Particle()->GetPdgCode() != def->GetMotherPDG()) continue;
762 // check that daughters match expected species
763 if (part->Particle()->GetNDaughters() < 2) continue;
764 label1 = part->Particle()->GetDaughter(0);
765 label2 = part->Particle()->GetDaughter(1);
766 daughter1 = (AliMCParticle*)fMCEvent->GetTrack(label1);
767 daughter2 = (AliMCParticle*)fMCEvent->GetTrack(label2);
769 if (TMath::Abs(daughter1->Particle()->GetPdgCode()) == def->GetPDG(0) && TMath::Abs(daughter2->Particle()->GetPdgCode()) == def->GetPDG(1)) {
771 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(0));
772 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(1));
773 } else if (TMath::Abs(daughter1->Particle()->GetPdgCode()) == def->GetPDG(1) && TMath::Abs(daughter2->Particle()->GetPdgCode()) == def->GetPDG(0)) {
775 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(1));
776 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(0));
778 if (!okMatch) continue;
779 // assign momenta to computation object
780 miniPair.Sum(0) = miniPair.Sum(1) = (p1 + p2);
781 miniPair.FillRef(def->GetMotherMass());
783 def->FillMother(&miniPair, miniEvent, &fValues);
788 //__________________________________________________________________________________________________
789 void AliRsnMiniAnalysisTask::FillTrueMotherAOD(AliRsnMiniEvent *miniEvent)
792 // Fills the histograms with true mother (AOD version)
796 TClonesArray *list = fRsnEvent.GetAODList();
797 Int_t id, ndef = fHistograms.GetEntries();
798 Int_t ip, label1, label2, npart = list->GetEntries();
799 static AliRsnMiniPair miniPair;
800 AliAODMCParticle *daughter1, *daughter2;
801 TLorentzVector p1, p2;
802 AliRsnMiniOutput *def = 0x0;
804 for (id = 0; id < ndef; id++) {
805 def = (AliRsnMiniOutput*)fHistograms[id];
807 if (!def->IsMother()) continue;
808 for (ip = 0; ip < npart; ip++) {
809 AliAODMCParticle *part = (AliAODMCParticle*)list->At(ip);
810 if (part->GetPdgCode() != def->GetMotherPDG()) continue;
811 // check that daughters match expected species
812 if (part->GetNDaughters() < 2) continue;
813 label1 = part->GetDaughter(0);
814 label2 = part->GetDaughter(1);
815 daughter1 = (AliAODMCParticle*)list->At(label1);
816 daughter2 = (AliAODMCParticle*)list->At(label2);
818 if (TMath::Abs(daughter1->GetPdgCode()) == def->GetPDG(0) && TMath::Abs(daughter2->GetPdgCode()) == def->GetPDG(1)) {
820 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(0));
821 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(1));
822 } else if (TMath::Abs(daughter1->GetPdgCode()) == def->GetPDG(1) && TMath::Abs(daughter2->GetPdgCode()) == def->GetPDG(0)) {
824 p1.SetXYZM(daughter1->Px(), daughter1->Py(), daughter1->Pz(), def->GetMass(1));
825 p2.SetXYZM(daughter2->Px(), daughter2->Py(), daughter2->Pz(), def->GetMass(0));
827 if (!okMatch) continue;
828 // assign momenta to computation object
829 miniPair.Sum(0) = miniPair.Sum(1) = (p1 + p2);
830 miniPair.FillRef(def->GetMotherMass());
832 def->FillMother(&miniPair, miniEvent, &fValues);
837 //__________________________________________________________________________________________________
838 Bool_t AliRsnMiniAnalysisTask::EventsMatch(AliRsnMiniEvent *event1, AliRsnMiniEvent *event2)
841 // Check if two events are compatible.
842 // If the mixing is continuous, this is true if differences in vz, mult and angle are smaller than
843 // the specified values.
844 // If the mixing is binned, this is true if the events are in the same bin.
847 if (!event1 || !event2) return kFALSE;
848 Int_t ivz1, ivz2, imult1, imult2, iangle1, iangle2;
850 if (fContinuousMix) {
851 if (TMath::Abs(event1->Vz() - event2->Vz() ) > fMaxDiffVz ) return kFALSE;
852 if (TMath::Abs(event1->Mult() - event2->Mult() ) > fMaxDiffMult ) return kFALSE;
853 if (TMath::Abs(event1->Angle() - event2->Angle()) > fMaxDiffAngle) return kFALSE;
856 ivz1 = (Int_t)(event1->Vz() / fMaxDiffVz);
857 ivz2 = (Int_t)(event2->Vz() / fMaxDiffVz);
858 imult1 = (Int_t)(event1->Mult() / fMaxDiffMult);
859 imult2 = (Int_t)(event2->Mult() / fMaxDiffMult);
860 iangle1 = (Int_t)(event1->Angle() / fMaxDiffAngle);
861 iangle2 = (Int_t)(event2->Angle() / fMaxDiffAngle);
862 if (ivz1 != ivz2) return kFALSE;
863 if (imult1 != imult2) return kFALSE;
864 if (iangle1 != iangle2) return kFALSE;