3 // All the definitions needed for building a RSN histogram
5 // -- properties of resonance (mass, PDG code if needed)
6 // -- properties of daughters (assigned mass, charges)
7 // -- definition of output histogram
10 #include "Riostream.h"
17 #include "THnSparse.h"
19 #include "TClonesArray.h"
21 #include "AliRsnMiniParticle.h"
22 #include "AliRsnMiniPair.h"
23 #include "AliRsnMiniEvent.h"
26 #include "AliRsnCutSet.h"
27 #include "AliRsnMiniAxis.h"
28 #include "AliRsnMiniOutput.h"
29 #include "AliRsnMiniValue.h"
31 ClassImp(AliRsnMiniOutput)
33 //__________________________________________________________________________________________________
34 AliRsnMiniOutput::AliRsnMiniOutput() :
37 fComputation(kComputations),
42 fAxes("AliRsnMiniAxis", 0),
51 fCutID[0] = fCutID[1] = -1;
52 fDaughter[0] = fDaughter[1] = AliRsnDaughter::kUnknown;
53 fCharge[0] = fCharge[1] = 0;
56 //__________________________________________________________________________________________________
57 AliRsnMiniOutput::AliRsnMiniOutput(const char *name, EOutputType type, EComputation src) :
65 fAxes("AliRsnMiniAxis", 0),
74 fCutID[0] = fCutID[1] = -1;
75 fDaughter[0] = fDaughter[1] = AliRsnDaughter::kUnknown;
76 fCharge[0] = fCharge[1] = 0;
79 //__________________________________________________________________________________________________
80 AliRsnMiniOutput::AliRsnMiniOutput(const char *name, const char *outType, const char *compType) :
83 fComputation(kComputations),
88 fAxes("AliRsnMiniAxis", 0),
94 // Constructor, with a more user friendly implementation, where
95 // the user sets the type of output and computations through conventional strings:
98 // -- "HIST" --> common histogram (up to 3 dimensions)
99 // -- "SPARSE" --> sparse histogram
102 // -- "EVENT" --> event-only computations
103 // -- "PAIR" --> track pair computations (default)
104 // -- "MIX" --> event mixing (like track pair, but different events)
105 // -- "ROTATE1" --> rotated background (rotate first track)
106 // -- "ROTATE2" --> rotated background (rotate second track)
107 // -- "TRUE" --> true pairs (like track pair, but checking that come from same mother)
108 // -- "MOTHER" --> mother (loop on MC directly for mothers --> denominator of efficiency)
113 // understand output type
116 if (!input.CompareTo("HIST"))
117 fOutputType = kHistogram;
118 else if (!input.CompareTo("SPARSE"))
119 fOutputType = kHistogramSparse;
121 AliWarning(Form("String '%s' does not define a meaningful output type", outType));
123 // understand computation type
126 if (!input.CompareTo("EVENT"))
127 fComputation = kEventOnly;
128 else if (!input.CompareTo("PAIR"))
129 fComputation = kTrackPair;
130 else if (!input.CompareTo("MIX"))
131 fComputation = kTrackPairMix;
132 else if (!input.CompareTo("ROTATE1"))
133 fComputation = kTrackPairRotated1;
134 else if (!input.CompareTo("ROTATE2"))
135 fComputation = kTrackPairRotated2;
136 else if (!input.CompareTo("TRUE"))
137 fComputation = kTruePair;
138 else if (!input.CompareTo("MOTHER"))
139 fComputation = kMother;
141 AliWarning(Form("String '%s' does not define a meaningful computation type", compType));
143 fCutID[0] = fCutID[1] = -1;
144 fDaughter[0] = fDaughter[1] = AliRsnDaughter::kUnknown;
145 fCharge[0] = fCharge[1] = 0;
148 //__________________________________________________________________________________________________
149 AliRsnMiniOutput::AliRsnMiniOutput(const AliRsnMiniOutput ©) :
151 fOutputType(copy.fOutputType),
152 fComputation(copy.fComputation),
153 fMotherPDG(copy.fMotherPDG),
154 fMotherMass(copy.fMotherMass),
155 fPairCuts(copy.fPairCuts),
156 fOutputID(copy.fOutputID),
158 fComputed(copy.fComputed),
167 for (i = 0; i < 2; i++) {
168 fCutID[i] = copy.fCutID[i];
169 fDaughter[i] = copy.fDaughter[i];
170 fCharge[i] = copy.fCharge[i];
174 //__________________________________________________________________________________________________
175 AliRsnMiniOutput& AliRsnMiniOutput::operator=(const AliRsnMiniOutput ©)
178 // Assignment operator
181 fOutputType = copy.fOutputType;
182 fComputation = copy.fComputation;
183 fMotherPDG = copy.fMotherPDG;
184 fMotherMass = copy.fMotherMass;
185 fPairCuts = copy.fPairCuts;
186 fOutputID = copy.fOutputID;
188 fComputed = copy.fComputed;
192 for (i = 0; i < 2; i++) {
193 fCutID[i] = copy.fCutID[i];
194 fDaughter[i] = copy.fDaughter[i];
195 fCharge[i] = copy.fCharge[i];
202 //__________________________________________________________________________________________________
203 void AliRsnMiniOutput::AddAxis(Int_t i, Int_t nbins, Double_t min, Double_t max)
206 // Create a new axis reference
209 Int_t size = fAxes.GetEntries();
210 new (fAxes[size]) AliRsnMiniAxis(i, nbins, min, max);
213 //__________________________________________________________________________________________________
214 void AliRsnMiniOutput::AddAxis(Int_t i, Double_t min, Double_t max, Double_t step)
217 // Create a new axis reference
220 Int_t size = fAxes.GetEntries();
221 new (fAxes[size]) AliRsnMiniAxis(i, min, max, step);
224 //__________________________________________________________________________________________________
225 void AliRsnMiniOutput::AddAxis(Int_t i, Int_t nbins, Double_t *values)
228 // Create a new axis reference
231 Int_t size = fAxes.GetEntries();
232 new (fAxes[size]) AliRsnMiniAxis(i, nbins, values);
235 //__________________________________________________________________________________________________
236 Bool_t AliRsnMiniOutput::Init(const char *prefix, TList *list)
239 // Initialize properly the histogram and add it to the argument list
243 AliError("Required an output list");
248 Int_t size = fAxes.GetEntries();
250 AliWarning(Form("[%s] Cannot initialize histogram with less than 1 axis", GetName()));
254 switch (fOutputType) {
257 CreateHistogram(Form("%s_%s", prefix, GetName()));
259 AliInfo(Form("[%s] Added %d > 3 axes. Creating a sparse histogram", GetName(), size));
260 fOutputType = kHistogramSparse;
261 CreateHistogramSparse(Form("%s_%s", prefix, GetName()));
264 case kHistogramSparse:
265 CreateHistogramSparse(Form("%s_%s", prefix, GetName()));
268 AliError("Wrong output histogram definition");
273 //__________________________________________________________________________________________________
274 void AliRsnMiniOutput::CreateHistogram(const char *name)
277 // Initialize the 'default' TH1 output object.
278 // In case one of the expected axes is NULL, the initialization fails.
281 Int_t size = fAxes.GetEntries();
282 AliInfo(Form("Histogram name = '%s', with %d axes", name, size));
284 // we expect to have maximum 3 axes in this case
285 AliRsnMiniAxis *xAxis = 0x0, *yAxis = 0x0, *zAxis = 0x0;
286 if (size >= 1) xAxis = (AliRsnMiniAxis*)fAxes[0];
287 if (size >= 2) yAxis = (AliRsnMiniAxis*)fAxes[1];
288 if (size >= 3) zAxis = (AliRsnMiniAxis*)fAxes[2];
290 // create histogram depending on the number of axes
292 if (xAxis && yAxis && zAxis) {
293 h1 = new TH3F(name, "", xAxis->NBins(), xAxis->BinArray(), yAxis->NBins(), yAxis->BinArray(), zAxis->NBins(), zAxis->BinArray());
294 } else if (xAxis && yAxis) {
295 h1 = new TH2F(name, "", xAxis->NBins(), xAxis->BinArray(), yAxis->NBins(), yAxis->BinArray());
297 h1 = new TH1F(name, "", xAxis->NBins(), xAxis->BinArray());
299 AliError("No axis was initialized");
303 // switch the correct computation of errors
307 fOutputID = fList->IndexOf(h1);
311 //________________________________________________________________________________________
312 void AliRsnMiniOutput::CreateHistogramSparse(const char *name)
315 // Initialize the THnSparse output object.
316 // In case one of the expected axes is NULL, the initialization fails.
319 Int_t size = fAxes.GetEntries();
320 AliInfo(Form("Sparse histogram name = '%s', with %d axes", name, size));
322 // retrieve binnings and sizes of all axes
323 // since the check for null values is done in Init(),
324 // we assume that here they must all be well defined
325 Int_t i, *nbins = new Int_t[size];
326 for (i = 0; i < size; i++) {
327 AliRsnMiniAxis *axis = (AliRsnMiniAxis*)fAxes[i];
328 nbins[i] = axis->NBins();
331 // create fHSparseogram
332 THnSparseF *h1 = new THnSparseF(name, "", size, nbins);
334 // update the various axes using the definitions given in the array of axes here
335 for (i = 0; i < size; i++) {
336 AliRsnMiniAxis *axis = (AliRsnMiniAxis*)fAxes[i];
337 h1->GetAxis(i)->Set(nbins[i], axis->BinArray());
347 fOutputID = fList->IndexOf(h1);
351 //________________________________________________________________________________________
352 Bool_t AliRsnMiniOutput::FillEvent(AliRsnMiniEvent *event, TClonesArray *valueList)
355 // Compute values for event-based computations (does not use the pair)
358 // check computation type
359 if (fComputation != kEventOnly) {
360 AliError("This method can be called only for event-based computations");
365 ComputeValues(event, valueList);
370 //________________________________________________________________________________________
371 Bool_t AliRsnMiniOutput::FillMother(const AliRsnMiniPair *pair, AliRsnMiniEvent *event, TClonesArray *valueList)
374 // Compute values for mother-based computations
377 // check computation type
378 if (fComputation != kMother) {
379 AliError("This method can be called only for mother-based computations");
383 // copy passed pair info
386 // check pair against cuts
387 if (fPairCuts) if (!fPairCuts->IsSelected(&fPair)) return kFALSE;
390 ComputeValues(event, valueList);
395 //________________________________________________________________________________________
396 Int_t AliRsnMiniOutput::FillPair(AliRsnMiniEvent *event1, AliRsnMiniEvent *event2, TClonesArray *valueList, Bool_t refFirst)
399 // Loops on the passed mini-event, and for each pair of particles
400 // which satisfy the charge and cut requirements defined here, add an entry.
401 // Returns the number of successful fillings.
402 // Last argument tells if the reference event for event-based values is the first or the second.
405 // check computation type
406 Bool_t okComp = kFALSE;
407 if (fComputation == kTrackPair) okComp = kTRUE;
408 if (fComputation == kTrackPairMix) okComp = kTRUE;
409 if (fComputation == kTrackPairRotated1) okComp = kTRUE;
410 if (fComputation == kTrackPairRotated2) okComp = kTRUE;
411 if (fComputation == kTruePair) okComp = kTRUE;
413 AliError(Form("[%s] This method can be called only for pair-based computations", GetName()));
418 Int_t i1, i2, start, nadded = 0;
419 AliRsnMiniParticle *p1, *p2;
421 // it is necessary to know if criteria for the two daughters are the same
422 // and if the two events are the same or not (mixing)
423 //Bool_t sameCriteria = ((fCharge[0] == fCharge[1]) && (fCutID[0] == fCutID[1]));
424 Bool_t sameCriteria = ((fCharge[0] == fCharge[1]) && (fDaughter[0] == fDaughter[1]));
425 Bool_t sameEvent = (event1->ID() == event2->ID());
427 TArrayI selected1 = event1->CountParticles(fCharge[0], fCutID[0]);
428 TArrayI selected2 = event2->CountParticles(fCharge[1], fCutID[1]);
429 TString selList1 = "";
430 TString selList2 = "";
431 Int_t n1 = selected1.GetSize();
432 Int_t n2 = selected2.GetSize();
433 for (i1 = 0; i1 < n1; i1++) selList1.Append(Form("%d ", selected1[i1]));
434 for (i2 = 0; i2 < n2; i2++) selList2.Append(Form("%d ", selected2[i2]));
435 AliDebugClass(1, Form("Particle #1: [%s] -- event ID = %6d -- required charge = %c -- required cut ID = %d --> found %4d tracks (%s)", (event1 == event2 ? "def" : "mix"), event1->ID(), fCharge[0], fCutID[0], n1, selList1.Data()));
436 AliDebugClass(1, Form("Particle #2: [%s] -- event ID = %6d -- required charge = %c -- required cut ID = %d --> found %4d tracks (%s)", (event1 == event2 ? "def" : "mix"), event2->ID(), fCharge[1], fCutID[1], n2, selList2.Data()));
438 AliDebugClass(1, "No pairs to mix");
443 for (i1 = 0; i1 < n1; i1++) {
444 p1 = event1->GetParticle(selected1[i1]);
445 //p1 = event1->GetParticle(i1);
446 //if (p1->Charge() != fCharge[0]) continue;
447 //if (!p1->HasCutBit(fCutID[0])) continue;
448 // define starting point for inner loop
449 // if daughter selection criteria (charge, cuts) are the same
450 // and the two events coincide, internal loop must start from
451 // the first track *after* current one;
452 // otherwise it starts from the beginning
453 start = ((sameEvent && sameCriteria) ? i1 + 1 : 0);
454 AliDebugClass(2, Form("Start point = %d", start));
456 for (i2 = start; i2 < n2; i2++) {
457 p2 = event2->GetParticle(selected2[i2]);
458 //p2 = event2->GetParticle(i2);
459 //if (p2->Charge() != fCharge[1]) continue;
460 //if (!p2->HasCutBit(fCutID[1])) continue;
461 // avoid to mix a particle with itself
462 if (sameEvent && (p1->Index() == p2->Index())) {
463 AliDebugClass(2, "Skipping same index");
467 fPair.Fill(p1, p2, GetMass(0), GetMass(1), fMotherMass);
468 // do rotation if needed
469 if (fComputation == kTrackPairRotated1) fPair.InvertP(kTRUE);
470 if (fComputation == kTrackPairRotated2) fPair.InvertP(kFALSE);
471 // if required, check that this is a true pair
472 if (fComputation == kTruePair) {
473 if (fPair.Mother() < 0) {
475 } else if (TMath::Abs(fPair.MotherPDG()) != fMotherPDG) {
478 Bool_t decayMatch = kFALSE;
479 if (p1->PDGAbs() == AliRsnDaughter::SpeciesPDG(fDaughter[0]) && p2->PDGAbs() == AliRsnDaughter::SpeciesPDG(fDaughter[1]))
481 if (p2->PDGAbs() == AliRsnDaughter::SpeciesPDG(fDaughter[0]) && p1->PDGAbs() == AliRsnDaughter::SpeciesPDG(fDaughter[1]))
483 if (!decayMatch) continue;
485 // check pair against cuts
487 if (!fPairCuts->IsSelected(&fPair)) {
488 AliDebugClass(2, Form("Pair rapidity = %f --> too large", fPair.Y(0)));
491 AliDebugClass(2, Form("Pair rapidity = %f --> ok", fPair.Y(0)));
494 // get computed values & fill histogram
496 if (refFirst) ComputeValues(event1, valueList); else ComputeValues(event2, valueList);
498 } // end internal loop
499 } // end external loop
501 AliDebugClass(1, Form("Pairs added in total = %4d", nadded));
505 //________________________________________________________________________________________
506 void AliRsnMiniOutput::ComputeValues(AliRsnMiniEvent *event, TClonesArray *valueList)
509 // Using the arguments and the internal 'fPair' data member,
510 // compute all values to be stored in the histogram
513 // check size of computed array
514 Int_t size = fAxes.GetEntries();
515 if (fComputed.GetSize() != size) fComputed.Set(size);
517 Int_t i, ival, nval = valueList->GetEntries();
519 for (i = 0; i < size; i++) {
521 AliRsnMiniAxis *axis = (AliRsnMiniAxis*)fAxes[i];
523 AliError("Null axis");
526 ival = axis->GetValueID();
527 if (ival < 0 || ival >= nval) {
528 AliError(Form("Required value #%d, while maximum is %d", ival, nval));
531 AliRsnMiniValue *val = (AliRsnMiniValue*)valueList->At(ival);
533 AliError(Form("Value in position #%d is NULL", ival));
536 // if none of the above exit points is taken, compute value
537 fComputed[i] = val->Eval(&fPair, event);
541 //________________________________________________________________________________________
542 void AliRsnMiniOutput::FillHistogram()
545 // Fills the internal histogram using the current values stored in the
546 // 'fComputed' array, in the order as they are stored, up to the max
547 // dimension of the initialized histogram itself.
550 // retrieve object from list
552 AliError("List pointer is NULL");
555 TObject *obj = fList->At(fOutputID);
557 if (obj->InheritsFrom(TH1F::Class())) {
558 ((TH1F*)obj)->Fill(fComputed[0]);
559 } else if (obj->InheritsFrom(TH2F::Class())) {
560 ((TH2F*)obj)->Fill(fComputed[0], fComputed[1]);
561 } else if (obj->InheritsFrom(TH3F::Class())) {
562 ((TH3F*)obj)->Fill(fComputed[0], fComputed[1], fComputed[2]);
563 } else if (obj->InheritsFrom(THnSparseF::Class())) {
564 ((THnSparseF*)obj)->Fill(fComputed.GetArray());
566 AliError("No output initialized");