1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 /* $Id: AliTHn.cxx 20164 2007-08-14 15:31:50Z morsch $ */
18 // Use AliTHn instead of AliCFContainer and your memory consumption will be drastically reduced
19 // As AliTHn derives from AliCFContainer, you can just replace your current AliCFContainer object by AliTHn
20 // Once you have the merged output, call FillParent() and you can use AliCFContainer as usual
22 // this storage container is optimized for small memory usage
23 // under/over flow bins do not exist
24 // sumw2 structure is float only and only create when the weight != 1
25 // all histogram functionality (projections, axis, ranges, etc) are taken from THnSparse by propagating
26 // the information up into the THnSparse structure (in the ananalysis *after* data processing and merging)
28 // the derivation from THnSparse is obviously against many OO rules. correct would be a common baseclass of THnSparse and THn.
30 // Author: Jan Fiete Grosse-Oetringhaus
34 #include "TCollection.h"
37 #include "THnSparse.h"
57 AliTHn::AliTHn(const Char_t* name, const Char_t* title,const Int_t nSelStep, const Int_t nVarIn, const Int_t* nBinIn) :
58 AliCFContainer(name, title, nSelStep, nVarIn, nBinIn),
72 for (Int_t i=0; i<fNVars; i++)
82 fValues = new TArrayF*[fNSteps];
83 fSumw2 = new TArrayF*[fNSteps];
85 for (Int_t i=0; i<fNSteps; i++)
92 AliTHn::AliTHn(const AliTHn &c) :
97 fValues(new TArrayF*[c.fNSteps]),
98 fSumw2(new TArrayF*[c.fNSteps]),
105 // AliTHn copy constructor
108 memset(fValues,0,fNSteps*sizeof(TArrayF*));
109 memset(fSumw2,0,fNSteps*sizeof(TArrayF*));
111 for (Int_t i=0; i<fNSteps; i++) {
112 if (c.fValues[i]) fValues[i] = new TArrayF(*(c.fValues[i]));
113 if (c.fSumw2[i]) fSumw2[i] = new TArrayF(*(c.fSumw2[i]));
127 delete[] fNbinsCache;
132 void AliTHn::DeleteContainers()
134 // delete data containers
136 for (Int_t i=0; i<fNSteps; i++)
138 if (fValues && fValues[i])
144 if (fSumw2 && fSumw2[i])
152 //____________________________________________________________________
153 AliTHn &AliTHn::operator=(const AliTHn &c)
155 // assigment operator
158 AliCFContainer::operator=(c);
162 for(Int_t i=0; i< fNSteps; ++i) {
171 fValues=new TArrayF*[fNSteps];
172 fSumw2=new TArrayF*[fNSteps];
173 memset(fValues,0,fNSteps*sizeof(TArrayF*));
174 memset(fSumw2,0,fNSteps*sizeof(TArrayF*));
176 for (Int_t i=0; i<fNSteps; i++) {
177 if (c.fValues[i]) fValues[i] = new TArrayF(*(c.fValues[i]));
178 if (c.fSumw2[i]) fSumw2[i] = new TArrayF(*(c.fSumw2[i]));
185 axisCache = new TAxis*[fNVars];
186 memcpy(axisCache, c.axisCache, fNVars*sizeof(TAxis*));
191 //____________________________________________________________________
192 void AliTHn::Copy(TObject& c) const
196 AliTHn& target = (AliTHn &) c;
198 AliCFContainer::Copy(target);
200 target.fNSteps = fNSteps;
201 target.fNBins = fNBins;
202 target.fNVars = fNVars;
206 for (Int_t i=0; i<fNSteps; i++)
209 target.fValues[i] = new TArrayF(*(fValues[i]));
211 target.fValues[i] = 0;
214 target.fSumw2[i] = new TArrayF(*(fSumw2[i]));
216 target.fSumw2[i] = 0;
220 //____________________________________________________________________
221 Long64_t AliTHn::Merge(TCollection* list)
223 // Merge a list of AliTHn objects with this (needed for
225 // Returns the number of merged objects (including this).
233 AliCFContainer::Merge(list);
235 TIterator* iter = list->MakeIterator();
239 while ((obj = iter->Next())) {
241 AliTHn* entry = dynamic_cast<AliTHn*> (obj);
245 for (Int_t i=0; i<fNSteps; i++)
247 if (entry->fValues[i])
250 fValues[i] = new TArrayF(fNBins);
252 for (Long64_t l = 0; l<fNBins; l++)
253 fValues[i]->GetArray()[l] += entry->fValues[i]->GetArray()[l];
256 if (entry->fSumw2[i])
259 fSumw2[i] = new TArrayF(fNBins);
261 for (Long64_t l = 0; l<fNBins; l++)
262 fSumw2[i]->GetArray()[l] += entry->fSumw2[i]->GetArray()[l];
272 void AliTHn::Fill(const Double_t *var, Int_t istep, Double_t weight)
279 axisCache = new TAxis*[fNVars];
280 fNbinsCache = new Int_t[fNVars];
281 for (Int_t i=0; i<fNVars; i++)
283 axisCache[i] = GetAxis(i, 0);
284 fNbinsCache[i] = axisCache[i]->GetNbins();
287 fLastVars = new Double_t[fNVars];
288 fLastBins = new Int_t[fNVars];
290 // initial values to prevent checking for 0 below
291 for (Int_t i=0; i<fNVars; i++)
293 fLastBins[i] = axisCache[i]->FindBin(var[i]);
294 fLastVars[i] = var[i];
298 // calculate global bin index
300 for (Int_t i=0; i<fNVars; i++)
302 bin *= fNbinsCache[i];
305 if (fLastVars[i] == var[i])
306 tmpBin = fLastBins[i];
309 tmpBin = axisCache[i]->FindBin(var[i]);
310 fLastBins[i] = tmpBin;
311 fLastVars[i] = var[i];
313 //Printf("%d", tmpBin);
315 // under/overflow not supported
316 if (tmpBin < 1 || tmpBin > fNbinsCache[i])
319 // bins start from 0 here
321 // Printf("%lld", bin);
326 fValues[istep] = new TArrayF(fNBins);
327 AliInfo(Form("Created values container for step %d", istep));
332 // initialize with already filled entries (which have been filled with weight == 1), in this case fSumw2 := fValues
335 fSumw2[istep] = new TArrayF(*fValues[istep]);
336 AliInfo(Form("Created sumw2 container for step %d", istep));
340 fValues[istep]->GetArray()[bin] += weight;
342 fSumw2[istep]->GetArray()[bin] += weight * weight;
344 // Printf("%f", fValues[istep][bin]);
347 // AliCFContainer::Fill(var, istep, weight);
350 Long64_t AliTHn::GetGlobalBinIndex(const Int_t* binIdx)
352 // calculates global bin index
353 // binIdx contains TAxis bin indexes
354 // here bin count starts at 0 because we do not have over/underflow bins
357 for (Int_t i=0; i<fNVars; i++)
359 bin *= GetAxis(i, 0)->GetNbins();
360 bin += binIdx[i] - 1;
366 void AliTHn::FillContainer(AliCFContainer* cont)
368 // fills the information stored in the buffer in this class into the container <cont>
370 for (Int_t i=0; i<fNSteps; i++)
375 Float_t* source = fValues[i]->GetArray();
376 // if fSumw2 is not stored, the sqrt of the number of bin entries in source is filled below; otherwise we use fSumw2
377 Float_t* sourceSumw2 = source;
379 sourceSumw2 = fSumw2[i]->GetArray();
381 THnSparse* target = cont->GetGrid(i)->GetGrid();
383 Int_t* binIdx = new Int_t[fNVars];
384 Int_t* nBins = new Int_t[fNVars];
385 for (Int_t j=0; j<fNVars; j++)
388 nBins[j] = target->GetAxis(j)->GetNbins();
395 // for (Int_t j=0; j<fNVars; j++)
396 // printf("%d ", binIdx[j]);
398 Long64_t globalBin = GetGlobalBinIndex(binIdx);
399 // Printf(" --> %lld", globalBin);
401 if (source[globalBin] != 0)
403 target->SetBinContent(binIdx, source[globalBin]);
404 target->SetBinError(binIdx, TMath::Sqrt(sourceSumw2[globalBin]));
411 for (Int_t j=fNVars-1; j>0; j--)
413 if (binIdx[j] > nBins[j])
420 if (binIdx[0] > nBins[0])
424 AliInfo(Form("Step %d: copied %lld entries out of %lld bins", i, count, GetGlobalBinIndex(binIdx)));
431 void AliTHn::FillParent()
433 // fills the information stored in the buffer in this class into the baseclass containers
438 void AliTHn::ReduceAxis()
440 // "removes" one axis by summing over the axis and putting the entry to bin 1
441 // TODO presently only implemented for the last axis
443 Int_t axis = fNVars-1;
445 for (Int_t i=0; i<fNSteps; i++)
450 Float_t* source = fValues[i]->GetArray();
451 Float_t* sourceSumw2 = 0;
453 sourceSumw2 = fSumw2[i]->GetArray();
455 THnSparse* target = GetGrid(i)->GetGrid();
457 Int_t* binIdx = new Int_t[fNVars];
458 Int_t* nBins = new Int_t[fNVars];
459 for (Int_t j=0; j<fNVars; j++)
462 nBins[j] = target->GetAxis(j)->GetNbins();
469 // sum over axis <axis>
470 Float_t sumValues = 0;
471 Float_t sumSumw2 = 0;
472 for (Int_t j=1; j<=nBins[axis]; j++)
475 Long64_t globalBin = GetGlobalBinIndex(binIdx);
476 sumValues += source[globalBin];
477 source[globalBin] = 0;
481 sumSumw2 += sourceSumw2[globalBin];
482 sourceSumw2[globalBin] = 0;
487 Long64_t globalBin = GetGlobalBinIndex(binIdx);
488 source[globalBin] = sumValues;
490 sourceSumw2[globalBin] = sumSumw2;
497 for (Int_t j=fNVars-2; j>0; j--)
499 if (binIdx[j] > nBins[j])
506 if (binIdx[0] > nBins[0])
510 AliInfo(Form("Step %d: reduced %lld bins to %lld entries", i, GetGlobalBinIndex(binIdx), count));