]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGLF/RESONANCES/AliRsnMiniOutput.cxx
Merge branch 'master' of http://git.cern.ch/pub/AliRoot
[u/mrichter/AliRoot.git] / PWGLF / RESONANCES / AliRsnMiniOutput.cxx
CommitLineData
03d23846 1//
2// Mini-Output
3// All the definitions needed for building a RSN histogram
4// including:
5// -- properties of resonance (mass, PDG code if needed)
6// -- properties of daughters (assigned mass, charges)
7// -- definition of output histogram
61f275d1 8//
03d23846 9
10#include "Riostream.h"
11
12#include "TH1.h"
13#include "TH2.h"
14#include "TH3.h"
15#include "TList.h"
45aa62b9 16#include "TMath.h"
03d23846 17#include "THnSparse.h"
18#include "TString.h"
19#include "TClonesArray.h"
20
21#include "AliRsnMiniParticle.h"
22#include "AliRsnMiniPair.h"
23#include "AliRsnMiniEvent.h"
088ca370 24#include "AliAODEvent.h"
03d23846 25
26#include "AliLog.h"
27#include "AliRsnCutSet.h"
28#include "AliRsnMiniAxis.h"
29#include "AliRsnMiniOutput.h"
30#include "AliRsnMiniValue.h"
31
32ClassImp(AliRsnMiniOutput)
33
34//__________________________________________________________________________________________________
35AliRsnMiniOutput::AliRsnMiniOutput() :
36 TNamed(),
37 fOutputType(kTypes),
38 fComputation(kComputations),
39 fMotherPDG(0),
40 fMotherMass(0.0),
41 fPairCuts(0x0),
42 fOutputID(-1),
43 fAxes("AliRsnMiniAxis", 0),
44 fComputed(0),
45 fPair(),
a2455d2a 46 fList(0x0),
47 fSel1(0),
74d60285 48 fSel2(0),
088ca370 49 fMaxNSisters(-1),
50 fCheckP(kFALSE),
74d60285 51 fCheckHistRange(kTRUE)
03d23846 52{
53//
54// Constructor
55//
56
57 fCutID[0] = fCutID[1] = -1;
58 fDaughter[0] = fDaughter[1] = AliRsnDaughter::kUnknown;
59 fCharge[0] = fCharge[1] = 0;
60}
61
62//__________________________________________________________________________________________________
63AliRsnMiniOutput::AliRsnMiniOutput(const char *name, EOutputType type, EComputation src) :
64 TNamed(name, ""),
65 fOutputType(type),
66 fComputation(src),
67 fMotherPDG(0),
68 fMotherMass(0.0),
69 fPairCuts(0x0),
70 fOutputID(-1),
71 fAxes("AliRsnMiniAxis", 0),
72 fComputed(0),
73 fPair(),
a2455d2a 74 fList(0x0),
75 fSel1(0),
74d60285 76 fSel2(0),
088ca370 77 fMaxNSisters(-1),
78 fCheckP(kFALSE),
74d60285 79 fCheckHistRange(kTRUE)
03d23846 80{
81//
82// Constructor
83//
84
85 fCutID[0] = fCutID[1] = -1;
86 fDaughter[0] = fDaughter[1] = AliRsnDaughter::kUnknown;
87 fCharge[0] = fCharge[1] = 0;
88}
89
90//__________________________________________________________________________________________________
91AliRsnMiniOutput::AliRsnMiniOutput(const char *name, const char *outType, const char *compType) :
92 TNamed(name, ""),
93 fOutputType(kTypes),
94 fComputation(kComputations),
95 fMotherPDG(0),
96 fMotherMass(0.0),
97 fPairCuts(0x0),
98 fOutputID(-1),
99 fAxes("AliRsnMiniAxis", 0),
100 fComputed(0),
101 fPair(),
a2455d2a 102 fList(0x0),
103 fSel1(0),
74d60285 104 fSel2(0),
088ca370 105 fMaxNSisters(-1),
106 fCheckP(kFALSE),
74d60285 107 fCheckHistRange(kTRUE)
03d23846 108{
109//
110// Constructor, with a more user friendly implementation, where
111// the user sets the type of output and computations through conventional strings:
112//
113// Output:
6aaeb33c 114// -- "HIST" --> common histogram (up to 3 dimensions)
115// -- "SPARSE" --> sparse histogram
61f275d1 116//
117// Computation:
6aaeb33c 118// -- "EVENT" --> event-only computations
119// -- "PAIR" --> track pair computations (default)
120// -- "MIX" --> event mixing (like track pair, but different events)
121// -- "ROTATE1" --> rotated background (rotate first track)
122// -- "ROTATE2" --> rotated background (rotate second track)
123// -- "TRUE" --> true pairs (like track pair, but checking that come from same mother)
124// -- "MOTHER" --> mother (loop on MC directly for mothers --> denominator of efficiency)
03d23846 125//
126
127 TString input;
61f275d1 128
03d23846 129 // understand output type
130 input = outType;
131 input.ToUpper();
132 if (!input.CompareTo("HIST"))
133 fOutputType = kHistogram;
134 else if (!input.CompareTo("SPARSE"))
135 fOutputType = kHistogramSparse;
136 else
137 AliWarning(Form("String '%s' does not define a meaningful output type", outType));
61f275d1 138
03d23846 139 // understand computation type
140 input = compType;
141 input.ToUpper();
142 if (!input.CompareTo("EVENT"))
143 fComputation = kEventOnly;
144 else if (!input.CompareTo("PAIR"))
145 fComputation = kTrackPair;
146 else if (!input.CompareTo("MIX"))
147 fComputation = kTrackPairMix;
6aaeb33c 148 else if (!input.CompareTo("ROTATE1"))
149 fComputation = kTrackPairRotated1;
150 else if (!input.CompareTo("ROTATE2"))
151 fComputation = kTrackPairRotated2;
03d23846 152 else if (!input.CompareTo("TRUE"))
153 fComputation = kTruePair;
154 else if (!input.CompareTo("MOTHER"))
155 fComputation = kMother;
156 else
157 AliWarning(Form("String '%s' does not define a meaningful computation type", compType));
61f275d1 158
03d23846 159 fCutID[0] = fCutID[1] = -1;
160 fDaughter[0] = fDaughter[1] = AliRsnDaughter::kUnknown;
161 fCharge[0] = fCharge[1] = 0;
162}
163
164//__________________________________________________________________________________________________
165AliRsnMiniOutput::AliRsnMiniOutput(const AliRsnMiniOutput &copy) :
166 TNamed(copy),
167 fOutputType(copy.fOutputType),
168 fComputation(copy.fComputation),
169 fMotherPDG(copy.fMotherPDG),
170 fMotherMass(copy.fMotherMass),
171 fPairCuts(copy.fPairCuts),
172 fOutputID(copy.fOutputID),
173 fAxes(copy.fAxes),
174 fComputed(copy.fComputed),
175 fPair(),
a2455d2a 176 fList(copy.fList),
177 fSel1(0),
74d60285 178 fSel2(0),
088ca370 179 fMaxNSisters(-1),
180 fCheckP(kFALSE),
74d60285 181 fCheckHistRange(copy.fCheckHistRange)
03d23846 182{
183//
184// Copy constructor
185//
186
187 Int_t i;
188 for (i = 0; i < 2; i++) {
189 fCutID[i] = copy.fCutID[i];
190 fDaughter[i] = copy.fDaughter[i];
191 fCharge[i] = copy.fCharge[i];
192 }
193}
194
195//__________________________________________________________________________________________________
61f275d1 196AliRsnMiniOutput &AliRsnMiniOutput::operator=(const AliRsnMiniOutput &copy)
03d23846 197{
198//
199// Assignment operator
200//
61f275d1 201 if (this == &copy)
202 return *this;
203 fOutputType = copy.fOutputType;
204 fComputation = copy.fComputation;
205 fMotherPDG = copy.fMotherPDG;
206 fMotherMass = copy.fMotherMass;
207 fPairCuts = copy.fPairCuts;
208 fOutputID = copy.fOutputID;
209 fAxes = copy.fAxes;
210 fComputed = copy.fComputed;
211 fList = copy.fList;
212
213 Int_t i;
214 for (i = 0; i < 2; i++) {
215 fCutID[i] = copy.fCutID[i];
216 fDaughter[i] = copy.fDaughter[i];
217 fCharge[i] = copy.fCharge[i];
218 }
219
220 fSel1.Set(0);
221 fSel2.Set(0);
088ca370 222 fMaxNSisters = copy.fMaxNSisters;
223 fCheckP = copy.fCheckP;
74d60285 224 fCheckHistRange = copy.fCheckHistRange;
61f275d1 225
03d23846 226 return (*this);
227}
228
229
230//__________________________________________________________________________________________________
231void AliRsnMiniOutput::AddAxis(Int_t i, Int_t nbins, Double_t min, Double_t max)
232{
233//
234// Create a new axis reference
235//
236
61f275d1 237 Int_t size = fAxes.GetEntries();
03d23846 238 new (fAxes[size]) AliRsnMiniAxis(i, nbins, min, max);
239}
240
241//__________________________________________________________________________________________________
242void AliRsnMiniOutput::AddAxis(Int_t i, Double_t min, Double_t max, Double_t step)
243{
244//
245// Create a new axis reference
246//
247
61f275d1 248 Int_t size = fAxes.GetEntries();
03d23846 249 new (fAxes[size]) AliRsnMiniAxis(i, min, max, step);
250}
251
252//__________________________________________________________________________________________________
253void AliRsnMiniOutput::AddAxis(Int_t i, Int_t nbins, Double_t *values)
254{
255//
256// Create a new axis reference
257//
258
61f275d1 259 Int_t size = fAxes.GetEntries();
03d23846 260 new (fAxes[size]) AliRsnMiniAxis(i, nbins, values);
261}
262
263//__________________________________________________________________________________________________
264Bool_t AliRsnMiniOutput::Init(const char *prefix, TList *list)
265{
266//
267// Initialize properly the histogram and add it to the argument list
268//
269
270 if (!list) {
271 AliError("Required an output list");
272 return kFALSE;
273 }
61f275d1 274
03d23846 275 fList = list;
45aa62b9 276 Int_t size = fAxes.GetEntries();
277 if (size < 1) {
278 AliWarning(Form("[%s] Cannot initialize histogram with less than 1 axis", GetName()));
279 return kFALSE;
280 }
03d23846 281
282 switch (fOutputType) {
283 case kHistogram:
d573d2fb 284 if (size <= 3) {
285 CreateHistogram(Form("%s_%s", prefix, GetName()));
286 } else {
287 AliInfo(Form("[%s] Added %d > 3 axes. Creating a sparse histogram", GetName(), size));
288 fOutputType = kHistogramSparse;
289 CreateHistogramSparse(Form("%s_%s", prefix, GetName()));
290 }
03d23846 291 return kTRUE;
292 case kHistogramSparse:
6aaeb33c 293 CreateHistogramSparse(Form("%s_%s", prefix, GetName()));
03d23846 294 return kTRUE;
295 default:
296 AliError("Wrong output histogram definition");
297 return kFALSE;
298 }
299}
300
301//__________________________________________________________________________________________________
302void AliRsnMiniOutput::CreateHistogram(const char *name)
303{
304//
305// Initialize the 'default' TH1 output object.
306// In case one of the expected axes is NULL, the initialization fails.
307//
308
309 Int_t size = fAxes.GetEntries();
310 AliInfo(Form("Histogram name = '%s', with %d axes", name, size));
311
312 // we expect to have maximum 3 axes in this case
313 AliRsnMiniAxis *xAxis = 0x0, *yAxis = 0x0, *zAxis = 0x0;
61f275d1 314 if (size >= 1) xAxis = (AliRsnMiniAxis *)fAxes[0];
315 if (size >= 2) yAxis = (AliRsnMiniAxis *)fAxes[1];
316 if (size >= 3) zAxis = (AliRsnMiniAxis *)fAxes[2];
317
03d23846 318 // create histogram depending on the number of axes
319 TH1 *h1 = 0x0;
320 if (xAxis && yAxis && zAxis) {
321 h1 = new TH3F(name, "", xAxis->NBins(), xAxis->BinArray(), yAxis->NBins(), yAxis->BinArray(), zAxis->NBins(), zAxis->BinArray());
322 } else if (xAxis && yAxis) {
323 h1 = new TH2F(name, "", xAxis->NBins(), xAxis->BinArray(), yAxis->NBins(), yAxis->BinArray());
324 } else if (xAxis) {
325 h1 = new TH1F(name, "", xAxis->NBins(), xAxis->BinArray());
326 } else {
327 AliError("No axis was initialized");
328 return;
329 }
61f275d1 330
03d23846 331 // switch the correct computation of errors
332 if (h1 && fList) {
333 h1->Sumw2();
334 fList->Add(h1);
335 fOutputID = fList->IndexOf(h1);
336 }
337}
338
339//________________________________________________________________________________________
340void AliRsnMiniOutput::CreateHistogramSparse(const char *name)
341{
342//
343// Initialize the THnSparse output object.
344// In case one of the expected axes is NULL, the initialization fails.
345//
346
d573d2fb 347 Int_t size = fAxes.GetEntries();
348 AliInfo(Form("Sparse histogram name = '%s', with %d axes", name, size));
61f275d1 349
03d23846 350 // retrieve binnings and sizes of all axes
351 // since the check for null values is done in Init(),
352 // we assume that here they must all be well defined
03d23846 353 Int_t i, *nbins = new Int_t[size];
354 for (i = 0; i < size; i++) {
61f275d1 355 AliRsnMiniAxis *axis = (AliRsnMiniAxis *)fAxes[i];
03d23846 356 nbins[i] = axis->NBins();
357 }
358
359 // create fHSparseogram
360 THnSparseF *h1 = new THnSparseF(name, "", size, nbins);
361
362 // update the various axes using the definitions given in the array of axes here
363 for (i = 0; i < size; i++) {
61f275d1 364 AliRsnMiniAxis *axis = (AliRsnMiniAxis *)fAxes[i];
03d23846 365 h1->GetAxis(i)->Set(nbins[i], axis->BinArray());
366 }
367
368 // clear heap
369 delete [] nbins;
61f275d1 370
03d23846 371 // add to list
372 if (h1 && fList) {
373 h1->Sumw2();
374 fList->Add(h1);
375 fOutputID = fList->IndexOf(h1);
376 }
377}
378
379//________________________________________________________________________________________
45aa62b9 380Bool_t AliRsnMiniOutput::FillEvent(AliRsnMiniEvent *event, TClonesArray *valueList)
03d23846 381{
382//
383// Compute values for event-based computations (does not use the pair)
384//
385
386 // check computation type
387 if (fComputation != kEventOnly) {
388 AliError("This method can be called only for event-based computations");
389 return kFALSE;
390 }
391
45aa62b9 392 // compute & fill
393 ComputeValues(event, valueList);
394 FillHistogram();
395 return kTRUE;
03d23846 396}
397
398//________________________________________________________________________________________
45aa62b9 399Bool_t AliRsnMiniOutput::FillMother(const AliRsnMiniPair *pair, AliRsnMiniEvent *event, TClonesArray *valueList)
03d23846 400{
401//
402// Compute values for mother-based computations
403//
404
405 // check computation type
406 if (fComputation != kMother) {
407 AliError("This method can be called only for mother-based computations");
408 return kFALSE;
409 }
61f275d1 410
03d23846 411 // copy passed pair info
412 fPair = (*pair);
61f275d1 413
03d23846 414 // check pair against cuts
415 if (fPairCuts) if (!fPairCuts->IsSelected(&fPair)) return kFALSE;
416
45aa62b9 417 // compute & fill
418 ComputeValues(event, valueList);
419 FillHistogram();
420 return kTRUE;
03d23846 421}
422
423//________________________________________________________________________________________
d573d2fb 424Int_t AliRsnMiniOutput::FillPair(AliRsnMiniEvent *event1, AliRsnMiniEvent *event2, TClonesArray *valueList, Bool_t refFirst)
03d23846 425{
426//
45aa62b9 427// Loops on the passed mini-event, and for each pair of particles
428// which satisfy the charge and cut requirements defined here, add an entry.
429// Returns the number of successful fillings.
d573d2fb 430// Last argument tells if the reference event for event-based values is the first or the second.
03d23846 431//
432
433 // check computation type
6aaeb33c 434 Bool_t okComp = kFALSE;
45aa62b9 435 if (fComputation == kTrackPair) okComp = kTRUE;
436 if (fComputation == kTrackPairMix) okComp = kTRUE;
437 if (fComputation == kTrackPairRotated1) okComp = kTRUE;
438 if (fComputation == kTrackPairRotated2) okComp = kTRUE;
439 if (fComputation == kTruePair) okComp = kTRUE;
6aaeb33c 440 if (!okComp) {
45aa62b9 441 AliError(Form("[%s] This method can be called only for pair-based computations", GetName()));
03d23846 442 return kFALSE;
443 }
61f275d1 444
45aa62b9 445 // loop variables
446 Int_t i1, i2, start, nadded = 0;
45aa62b9 447 AliRsnMiniParticle *p1, *p2;
61f275d1 448
45aa62b9 449 // it is necessary to know if criteria for the two daughters are the same
450 // and if the two events are the same or not (mixing)
7196ee4f 451 //Bool_t sameCriteria = ((fCharge[0] == fCharge[1]) && (fCutID[0] == fCutID[1]));
452 Bool_t sameCriteria = ((fCharge[0] == fCharge[1]) && (fDaughter[0] == fDaughter[1]));
45aa62b9 453 Bool_t sameEvent = (event1->ID() == event2->ID());
61f275d1 454
9e3a9020 455 TString selList1 = "";
456 TString selList2 = "";
a2455d2a 457 Int_t n1 = event1->CountParticles(fSel1, fCharge[0], fCutID[0]);
458 Int_t n2 = event2->CountParticles(fSel2, fCharge[1], fCutID[1]);
459 for (i1 = 0; i1 < n1; i1++) selList1.Append(Form("%d ", fSel1[i1]));
460 for (i2 = 0; i2 < n2; i2++) selList2.Append(Form("%d ", fSel2[i2]));
461 AliDebugClass(1, Form("[%10s] Part #1: [%s] -- evID %6d -- charge = %c -- cut ID = %d --> %4d tracks (%s)", GetName(), (event1 == event2 ? "def" : "mix"), event1->ID(), fCharge[0], fCutID[0], n1, selList1.Data()));
462 AliDebugClass(1, Form("[%10s] Part #2: [%s] -- evID %6d -- charge = %c -- cut ID = %d --> %4d tracks (%s)", GetName(), (event1 == event2 ? "def" : "mix"), event2->ID(), fCharge[1], fCutID[1], n2, selList2.Data()));
9e3a9020 463 if (!n1 || !n2) {
d573d2fb 464 AliDebugClass(1, "No pairs to mix");
465 return 0;
466 }
61f275d1 467
45aa62b9 468 // external loop
469 for (i1 = 0; i1 < n1; i1++) {
a2455d2a 470 p1 = event1->GetParticle(fSel1[i1]);
9e3a9020 471 //p1 = event1->GetParticle(i1);
472 //if (p1->Charge() != fCharge[0]) continue;
473 //if (!p1->HasCutBit(fCutID[0])) continue;
45aa62b9 474 // define starting point for inner loop
475 // if daughter selection criteria (charge, cuts) are the same
476 // and the two events coincide, internal loop must start from
477 // the first track *after* current one;
478 // otherwise it starts from the beginning
479 start = ((sameEvent && sameCriteria) ? i1 + 1 : 0);
7196ee4f 480 AliDebugClass(2, Form("Start point = %d", start));
45aa62b9 481 // internal loop
482 for (i2 = start; i2 < n2; i2++) {
a2455d2a 483 p2 = event2->GetParticle(fSel2[i2]);
9e3a9020 484 //p2 = event2->GetParticle(i2);
485 //if (p2->Charge() != fCharge[1]) continue;
486 //if (!p2->HasCutBit(fCutID[1])) continue;
45aa62b9 487 // avoid to mix a particle with itself
488 if (sameEvent && (p1->Index() == p2->Index())) {
d573d2fb 489 AliDebugClass(2, "Skipping same index");
45aa62b9 490 continue;
491 }
492 // sum momenta
493 fPair.Fill(p1, p2, GetMass(0), GetMass(1), fMotherMass);
494 // do rotation if needed
495 if (fComputation == kTrackPairRotated1) fPair.InvertP(kTRUE);
496 if (fComputation == kTrackPairRotated2) fPair.InvertP(kFALSE);
497 // if required, check that this is a true pair
498 if (fComputation == kTruePair) {
499 if (fPair.Mother() < 0) {
500 continue;
55de729a 501 } else if (fPair.MotherPDG() != fMotherPDG) {
45aa62b9 502 continue;
503 }
504 Bool_t decayMatch = kFALSE;
505 if (p1->PDGAbs() == AliRsnDaughter::SpeciesPDG(fDaughter[0]) && p2->PDGAbs() == AliRsnDaughter::SpeciesPDG(fDaughter[1]))
506 decayMatch = kTRUE;
507 if (p2->PDGAbs() == AliRsnDaughter::SpeciesPDG(fDaughter[0]) && p1->PDGAbs() == AliRsnDaughter::SpeciesPDG(fDaughter[1]))
508 decayMatch = kTRUE;
509 if (!decayMatch) continue;
35b36c39 510 if ( (fMaxNSisters>0) && (p1->NTotSisters()==p2->NTotSisters()) && (p1->NTotSisters()>fMaxNSisters)) continue;
511 if ( fCheckP &&(TMath::Abs(fPair.PmotherX()-(p1->Px(1)+p2->Px(1)))/(TMath::Abs(fPair.PmotherX())+1.e-13)) > 0.00001 &&
512 (TMath::Abs(fPair.PmotherY()-(p1->Py(1)+p2->Py(1)))/(TMath::Abs(fPair.PmotherY())+1.e-13)) > 0.00001 &&
513 (TMath::Abs(fPair.PmotherZ()-(p1->Pz(1)+p2->Pz(1)))/(TMath::Abs(fPair.PmotherZ())+1.e-13)) > 0.00001 ) continue;
45aa62b9 514 }
515 // check pair against cuts
516 if (fPairCuts) {
9e7b94f5 517 if (!fPairCuts->IsSelected(&fPair)) continue;
45aa62b9 518 }
519 // get computed values & fill histogram
9e3a9020 520 nadded++;
61f275d1 521 if (refFirst) ComputeValues(event1, valueList); else ComputeValues(event2, valueList);
45aa62b9 522 FillHistogram();
45aa62b9 523 } // end internal loop
524 } // end external loop
61f275d1 525
d573d2fb 526 AliDebugClass(1, Form("Pairs added in total = %4d", nadded));
45aa62b9 527 return nadded;
03d23846 528}
529
530//________________________________________________________________________________________
45aa62b9 531void AliRsnMiniOutput::ComputeValues(AliRsnMiniEvent *event, TClonesArray *valueList)
03d23846 532{
533//
534// Using the arguments and the internal 'fPair' data member,
535// compute all values to be stored in the histogram
536//
537
538 // check size of computed array
539 Int_t size = fAxes.GetEntries();
540 if (fComputed.GetSize() != size) fComputed.Set(size);
541
542 Int_t i, ival, nval = valueList->GetEntries();
61f275d1 543
03d23846 544 for (i = 0; i < size; i++) {
545 fComputed[i] = 1E20;
61f275d1 546 AliRsnMiniAxis *axis = (AliRsnMiniAxis *)fAxes[i];
03d23846 547 if (!axis) {
548 AliError("Null axis");
549 continue;
550 }
551 ival = axis->GetValueID();
552 if (ival < 0 || ival >= nval) {
553 AliError(Form("Required value #%d, while maximum is %d", ival, nval));
554 continue;
555 }
61f275d1 556 AliRsnMiniValue *val = (AliRsnMiniValue *)valueList->At(ival);
03d23846 557 if (!val) {
558 AliError(Form("Value in position #%d is NULL", ival));
559 continue;
61f275d1 560 }
03d23846 561 // if none of the above exit points is taken, compute value
562 fComputed[i] = val->Eval(&fPair, event);
563 }
03d23846 564}
565
566//________________________________________________________________________________________
45aa62b9 567void AliRsnMiniOutput::FillHistogram()
03d23846 568{
569//
570// Fills the internal histogram using the current values stored in the
571// 'fComputed' array, in the order as they are stored, up to the max
572// dimension of the initialized histogram itself.
573//
574
575 // retrieve object from list
576 if (!fList) {
577 AliError("List pointer is NULL");
45aa62b9 578 return;
03d23846 579 }
580 TObject *obj = fList->At(fOutputID);
581
582 if (obj->InheritsFrom(TH1F::Class())) {
61f275d1 583 ((TH1F *)obj)->Fill(fComputed[0]);
03d23846 584 } else if (obj->InheritsFrom(TH2F::Class())) {
61f275d1 585 ((TH2F *)obj)->Fill(fComputed[0], fComputed[1]);
03d23846 586 } else if (obj->InheritsFrom(TH3F::Class())) {
61f275d1 587 ((TH3F *)obj)->Fill(fComputed[0], fComputed[1], fComputed[2]);
03d23846 588 } else if (obj->InheritsFrom(THnSparseF::Class())) {
74d60285 589 THnSparseF *h = (THnSparseF *)obj;
590 if (fCheckHistRange) {
591 for (Int_t iAxis = 0; iAxis<h->GetNdimensions(); iAxis++) {
592 if (fComputed.At(iAxis)>h->GetAxis(iAxis)->GetXmax() || fComputed.At(iAxis)<h->GetAxis(iAxis)->GetXmin()) return;
593 }
594 }
595 h->Fill(fComputed.GetArray());
03d23846 596 } else {
597 AliError("No output initialized");
03d23846 598 }
03d23846 599}