LCOV - code coverage report
Current view: top level - STEER/STEERBase - AliCounterCollection.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 858 0.1 %
Date: 2016-06-14 17:26:59 Functions: 1 45 2.2 %

          Line data    Source code
       1             : /**************************************************************************
       2             :  * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
       3             :  *                                                                        *
       4             :  * Author: The ALICE Off-line Project.                                    *
       5             :  * Contributors are mentioned in the code where appropriate.              *
       6             :  *                                                                        *
       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             :  **************************************************************************/
      15             : 
      16             : /* $Id$ */
      17             : 
      18             : //-----------------------------------------------------------------------------
      19             : /// \class AliCounterCollection
      20             : /// 
      21             : /// generic class to handle a collection of counters
      22             : ///
      23             : /// \author Philippe Pillot
      24             : //-----------------------------------------------------------------------------
      25             : 
      26             : #include "AliCounterCollection.h"
      27             : 
      28             : #include <limits.h>
      29             : 
      30             : #include <AliLog.h>
      31             : 
      32             : #include <TString.h>
      33             : #include <TObjString.h>
      34             : #include <TObjArray.h>
      35             : #include <THnSparse.h>
      36             : #include <THashList.h>
      37             : #include <TArrayI.h>
      38             : #include <TH1D.h>
      39             : #include <TH2D.h>
      40             : #include <TCollection.h>
      41             : 
      42         176 : ClassImp(AliCounterCollection)
      43             : 
      44             : //-----------------------------------------------------------------------
      45             : AliCounterCollection::AliCounterCollection(const char* name) :
      46           0 : TNamed(name,name),
      47           0 : fRubrics(new THashList(10)),
      48           0 : fRubricsSize(new TArrayI(10)),
      49           0 : fCounters(0x0),
      50           0 : fWeightedCounters(kFALSE),
      51           0 : fLongCounters(kFALSE)
      52           0 : {
      53             :   /// Constructor
      54           0 :   fRubrics->SetOwner();
      55           0 : }
      56             : 
      57             : //-----------------------------------------------------------------------
      58             : AliCounterCollection::~AliCounterCollection()
      59           0 : {
      60             :   /// Destructor
      61           0 :   delete fRubrics;
      62           0 :   delete fRubricsSize;
      63           0 :   delete fCounters;
      64           0 : }
      65             : 
      66             : //-----------------------------------------------------------------------
      67             : void AliCounterCollection::Clear(Option_t*)
      68             : {
      69             :   /// Clear counters
      70           0 :   fRubrics->Clear();
      71           0 :   fRubricsSize->Reset();
      72           0 :   delete fCounters; fCounters = 0x0;
      73           0 :   fWeightedCounters = kFALSE;
      74           0 :   fLongCounters = kFALSE;
      75           0 : }
      76             : 
      77             : //-----------------------------------------------------------------------
      78             : void AliCounterCollection::AddRubric(TString name, TString listOfKeyWords)
      79             : {
      80             :   /// Add a new rubric with the complete list of related key words separated by "/".
      81             :   /// If the key word "any" is not defined, the overall statistics is
      82             :   /// assumed to be the sum of the statistics under each key word.
      83             :   
      84           0 :   name.ToUpper();
      85           0 :   listOfKeyWords.ToUpper();
      86             :   
      87           0 :   if (fRubrics->Contains(name.Data())) {
      88           0 :     AliError(Form("rubric named %s already exist",name.Data()));
      89           0 :     return;
      90             :   }
      91             :   
      92             :   // add the list of autorized key words
      93           0 :   TObjArray* rubric = listOfKeyWords.Tokenize("/");
      94           0 :   CleanListOfStrings(rubric);
      95           0 :   rubric->SetName(name.Data());
      96           0 :   Int_t nRubrics = fRubrics->GetSize();
      97           0 :   rubric->SetUniqueID(nRubrics);
      98           0 :   fRubrics->AddLast(rubric);
      99             :   
     100             :   // save the number of autorized key words (expand the array if needed)
     101           0 :   if (nRubrics+1 > fRubricsSize->GetSize()) fRubricsSize->Set(2*fRubricsSize->GetSize());
     102           0 :   (*fRubricsSize)[nRubrics] = rubric->GetEntriesFast();
     103           0 : }
     104             : 
     105             : //-----------------------------------------------------------------------
     106             : void AliCounterCollection::AddRubric(TString name, Int_t maxNKeyWords)
     107             : {
     108             :   /// Add a new rubric containing at maximum maxNKeyWords key words.
     109             :   /// Key words will be added as the counters get filled until the maximum is reached.
     110             :   /// If the key word "any" is never defined, the overall statistics is
     111             :   /// assumed to be the sum of the statistics under each key word.
     112             :   
     113           0 :   name.ToUpper();
     114             :   
     115           0 :   if (fRubrics->Contains(name.Data())) {
     116           0 :     AliError(Form("rubric named %s already exist",name.Data()));
     117           0 :     return;
     118             :   }
     119             :   
     120             :   // create the empty rubric
     121           0 :   TObjString* rubric = new TObjString(name.Data());
     122           0 :   Int_t nRubrics = fRubrics->GetSize();
     123           0 :   rubric->SetUniqueID(nRubrics);
     124           0 :   fRubrics->AddLast(rubric);
     125             :   
     126             :   // save the maximum number of autorized key words
     127           0 :   if (nRubrics+1 > fRubricsSize->GetSize()) fRubricsSize->Set(2*fRubricsSize->GetSize());
     128           0 :   (*fRubricsSize)[nRubrics] = maxNKeyWords;
     129           0 : }
     130             : 
     131             : //-----------------------------------------------------------------------
     132             : void AliCounterCollection::Init(Bool_t weightedCounters)
     133             : {
     134             :   /// Initialize the internal counters from the added rubrics.
     135             :   
     136             :   // create the counters
     137           0 :   delete fCounters;
     138           0 :   fWeightedCounters = weightedCounters;
     139           0 :   if (fWeightedCounters)
     140           0 :     fCounters = new THnSparseT<TArrayF>("hCounters", "hCounters", fRubrics->GetSize(), fRubricsSize->GetArray(), 0x0, 0x0);
     141             :   else
     142           0 :     fCounters = new THnSparseT<TArrayI>("hCounters", "hCounters", fRubrics->GetSize(), fRubricsSize->GetArray(), 0x0, 0x0);
     143             :   
     144             :   // loop over axis
     145             :   TObject* rubric = 0x0;
     146           0 :   TIter nextRubric(fRubrics);
     147           0 :   while ((rubric = nextRubric())) {
     148           0 :     TAxis* axis = fCounters->GetAxis((Int_t)rubric->GetUniqueID());
     149             :     
     150             :     // set axis name
     151           0 :     axis->SetName(rubric->GetName());
     152             :     
     153             :     // set labels if already known
     154           0 :     TObjArray* keyWords = dynamic_cast<TObjArray*>(rubric);
     155           0 :     if (keyWords) {
     156             :       TObjString* label = 0x0;
     157             :       Int_t bin = 1;
     158           0 :       TIter nextLabel(keyWords);
     159           0 :       while ((label = static_cast<TObjString*>(nextLabel()))) axis->SetBinLabel(bin++, label->String().Data());
     160           0 :     }
     161             :     
     162             :   }
     163             :   
     164           0 : }
     165             : 
     166             : //-----------------------------------------------------------------------
     167             : Int_t AliCounterCollection::GetNActiveBins(Int_t dim)
     168             : {
     169             :   /// return the number of labels in that rubric.
     170           0 :   THashList* labels = fCounters->GetAxis(dim)->GetLabels();
     171           0 :   return (labels) ? labels->GetSize() : 0;
     172             : }
     173             : 
     174             : //-----------------------------------------------------------------------
     175             : Bool_t AliCounterCollection::ContainsAny(Int_t dim)
     176             : {
     177             :   /// return kTRUE if that rubric contains the keyWord "ANY".
     178           0 :   THashList* labels = fCounters->GetAxis(dim)->GetLabels();
     179           0 :   return (labels && labels->Contains("ANY"));
     180             : }
     181             : 
     182             : //-----------------------------------------------------------------------
     183             : const Int_t* AliCounterCollection::FindBins(const TString& externalKey, Bool_t allocate, Int_t& nEmptySlots)
     184             : {
     185             :   /// Return the corresponding bins ordered by rubric or 0x0 if externalKey is not valid.
     186             :   /// The externalKey format must be rubric:keyWord/rubric:keyWord/rubric:keyWord/...
     187             :   /// If allocate = kTRUE, new key words are added to the corresponding rubric if possible.
     188             :   /// If a rubric is not filled in, the coresponding slot contain -1 in the array.
     189             :   /// It is the responsability of the user to delete the returned array.
     190             :   
     191             :   // produce an empty array of keys
     192           0 :   Int_t nRubrics = fRubrics->GetSize();
     193           0 :   Int_t* bins = new Int_t[nRubrics];
     194           0 :   for (Int_t i=0; i<nRubrics; i++) bins[i] = -1;
     195           0 :   nEmptySlots = nRubrics;
     196             :   Bool_t isValid = kTRUE;
     197             :   
     198             :   // get the list of rubric:keyWord pairs
     199           0 :   TObjArray* rubricKeyPairs = externalKey.Tokenize("/");
     200             :   
     201             :   // loop over each rubric:keyWord pair
     202             :   TObjString* pair = 0x0;
     203           0 :   TIter next(rubricKeyPairs);
     204           0 :   while ((pair = static_cast<TObjString*>(next()))) {
     205             :     
     206             :     // get both rubric and associated key word
     207           0 :     TObjArray* rubricKeyPair = pair->String().Tokenize(":");
     208             :     
     209             :     // check the format of the pair
     210           0 :     if (rubricKeyPair->GetEntriesFast() != 2) {
     211           0 :       AliError("invalid key format");
     212             :       isValid = kFALSE;
     213           0 :       delete rubricKeyPair;
     214           0 :       break;
     215             :     }
     216             :     
     217             :     // get the axis corresponding to that rubric
     218           0 :     Int_t dim = FindDim(static_cast<TObjString*>(rubricKeyPair->UncheckedAt(0))->String());
     219           0 :     if (dim < 0) {
     220             :       isValid = kFALSE;
     221           0 :       delete rubricKeyPair;
     222           0 :       break;
     223             :     }
     224             :     
     225             :     // find the bin corresponding to that key word
     226           0 :     Int_t bin = FindBin(dim, static_cast<TObjString*>(rubricKeyPair->UncheckedAt(1))->String(), allocate);
     227           0 :     if (bin < 0) {
     228             :       isValid = kFALSE;
     229           0 :       delete rubricKeyPair;
     230           0 :       break;
     231             :     }
     232             :     
     233             :     // check if the array of keys already contains something for that rubric
     234           0 :     if (bins[dim] >= 0) {
     235           0 :       AliWarning("key already given for that rubric --> ignored");
     236           0 :       delete rubricKeyPair;
     237           0 :       continue;
     238             :     }
     239             :     
     240             :     // store the corresponding bin for that slot
     241           0 :     bins[dim] = bin;
     242           0 :     nEmptySlots--;
     243             :     
     244             :     // clean memory
     245           0 :     delete rubricKeyPair;
     246           0 :   }
     247             :   
     248             :   // delete the array in case of problem
     249           0 :   if (!isValid) {
     250           0 :     delete[] bins;
     251             :     bins = 0x0;
     252           0 :     nEmptySlots = nRubrics;
     253           0 :   }
     254             :   
     255             :   // clean memory
     256           0 :   delete rubricKeyPairs;
     257             :   
     258             :   return bins;
     259           0 : }
     260             : 
     261             : //-----------------------------------------------------------------------
     262             : Int_t AliCounterCollection::FindDim(const TString& rubricName) const
     263             : {
     264             :   /// Return the dimension corresponding to that rubric (or -1 in case of failure).
     265           0 :   TObject* rubric = fRubrics->FindObject(rubricName.Data());
     266           0 :   if (!rubric) {
     267           0 :     AliError(Form("invalid rubric: %s",rubricName.Data()));
     268           0 :     return -1;
     269             :   }
     270           0 :   return (Int_t) rubric->GetUniqueID();
     271           0 : }
     272             : 
     273             : //-----------------------------------------------------------------------
     274             : Int_t AliCounterCollection::FindBin(Int_t dim, const TString& keyWord, Bool_t allocate)
     275             : {
     276             :   /// Return the bin number corresponding to that key word (or -1 in case of failure).
     277             :   /// If allocate = kTRUE, try to add the key word if possible.
     278             :   
     279           0 :   TAxis* axis = fCounters->GetAxis(dim);
     280             :   
     281             :   // look for the bin corresponding to keyWord
     282           0 :   THashList* labels = axis->GetLabels();
     283           0 :   TObjString* label = (labels) ? static_cast<TObjString*>(labels->FindObject(keyWord.Data())) : 0x0;
     284           0 :   Int_t bin = (label) ? (Int_t)label->GetUniqueID() : -1;
     285             :   
     286             :   // in case the keyWord does not exist, try to add it if required
     287           0 :   if (bin<0 && allocate) {
     288           0 :     Int_t nLabels = (labels) ? labels->GetSize() : 0;
     289           0 :     if (nLabels < axis->GetNbins()) {
     290           0 :       bin = nLabels+1;
     291           0 :       axis->SetBinLabel(bin, keyWord.Data());
     292           0 :     }
     293           0 :   }
     294             :   
     295           0 :   if (bin<0) AliError(Form("invalid key word: %s:%s",axis->GetName(),keyWord.Data()));
     296             :   
     297           0 :   return bin;
     298             : }
     299             : 
     300             : //-----------------------------------------------------------------------
     301             : Short_t** AliCounterCollection::DecodeSelection(const TString& selections, const TObjArray& displayedRubrics)
     302             : {
     303             :   /// Tag the selected keywords in each rubric (-1=subtract; 0=discard; 1=add). Format:
     304             :   /// "rubric:[any-]keyWord,keyWord,../rubric:[any-]keyWord,.." (order does not matter).
     305             :   /// It is the responsability of the user to delete the returned array.
     306             :   
     307             :   // produce an empty array of selected keys
     308           0 :   Int_t nRubrics = fCounters->GetNdimensions();
     309           0 :   Short_t** selects = new Short_t*[nRubrics];
     310           0 :   for (Int_t i=0; i<nRubrics; i++) selects[i] = 0x0;
     311             :   
     312             :   // get the list of rubric:LisOfKeyWord pairs
     313           0 :   TObjArray* rubricKeyPairs = selections.Tokenize("/");
     314             :   
     315             :   // loop over each rubric:keyWord pair
     316             :   TObjString* pair = 0x0;
     317           0 :   TIter next(rubricKeyPairs);
     318           0 :   while ((pair = static_cast<TObjString*>(next()))) {
     319             :     
     320             :     // get both rubric and associated list of key words
     321           0 :     TObjArray* rubricKeyPair = pair->String().Tokenize(":");
     322             :     
     323             :     // check the format of the pair
     324           0 :     if (rubricKeyPair->GetEntriesFast() != 2) {
     325           0 :       AliError("invalid key format");
     326           0 :       delete rubricKeyPair;
     327           0 :       delete rubricKeyPairs;
     328           0 :       for (Int_t i=0; i<nRubrics; i++) if (selects[i]) delete[] selects[i];
     329           0 :       delete[] selects;
     330           0 :       return 0x0;
     331             :     }
     332             :     
     333             :     // check wether to select or to discard the keyWords
     334             :     Int_t include = kTRUE;
     335           0 :     TString ListOfKeyWords(static_cast<TObjString*>(rubricKeyPair->UncheckedAt(1))->String());
     336           0 :     if (ListOfKeyWords.BeginsWith("ANY-")) {
     337           0 :       ListOfKeyWords.Remove(0,4);
     338             :       include = kFALSE;
     339           0 :     }
     340             :     
     341             :     // select the key words
     342           0 :     const TString& rubric = static_cast<TObjString*>(rubricKeyPair->UncheckedAt(0))->String();
     343           0 :     if (!Select(include, rubric, ListOfKeyWords, displayedRubrics.Contains(rubric.Data()), selects)) {
     344           0 :       delete rubricKeyPair;
     345           0 :       delete rubricKeyPairs;
     346           0 :       for (Int_t i=0; i<nRubrics; i++) if (selects[i]) delete[] selects[i];
     347           0 :       delete[] selects;
     348           0 :       return 0x0;
     349             :     }
     350             :     
     351             :     // clean memory
     352           0 :     delete rubricKeyPair;
     353           0 :   }
     354             :   
     355             :   // clean memory
     356           0 :   delete rubricKeyPairs;
     357             :   
     358             :   // complete the selection of other rubrics
     359           0 :   for (Int_t i=0; i<nRubrics; i++) {
     360             :     
     361             :     // skip already processed rubrics
     362           0 :     if (selects[i]) continue;
     363             :     
     364             :     // create the list of bins
     365           0 :     Int_t nBins = GetNActiveBins(i) + 1;
     366           0 :     selects[i] = new Short_t[nBins];
     367             :     
     368             :     // select all key words or only the key work "ANY"
     369           0 :     if (ContainsAny(i) && !displayedRubrics.Contains(fCounters->GetAxis(i)->GetName())) {
     370           0 :       memset(selects[i], 0, sizeof(Short_t) * nBins);
     371           0 :       selects[i][FindBin(i, "ANY", kFALSE)] = 1;
     372           0 :     } else for (Int_t j=0; j<nBins; j++) selects[i][j] = 1;
     373             :     
     374           0 :   }
     375             :   
     376           0 :   return selects;
     377           0 : }
     378             : 
     379             : //-----------------------------------------------------------------------
     380             : Bool_t AliCounterCollection::Select(Bool_t include, const TString& rubric, const TString& keywords,
     381             :                                     Bool_t displayed, Short_t* selectBins[])
     382             : {
     383             :   /// Tag the selected keywords (separated by ',') in that rubric (-1=subtract; 0=discard; 1=add).
     384             :   
     385           0 :   Int_t dim = FindDim(rubric);
     386           0 :   if (dim < 0) return kFALSE;
     387             :   
     388           0 :   if (selectBins[dim]) {
     389           0 :     AliWarning(Form("selection already made for rubric %s --> ignored",rubric.Data()));
     390           0 :     return kTRUE;
     391             :   }
     392             :   
     393             :   // get list of key words to select
     394           0 :   TObjArray* keys = keywords.Tokenize(",");
     395           0 :   if (keys->GetEntriesFast() == 0) {
     396           0 :     AliError(Form("no key word specified for rubric %s",rubric.Data()));
     397           0 :     delete keys;
     398           0 :     return kFALSE;
     399             :   }
     400             :   
     401             :   // create the list of bins
     402           0 :   Int_t nBins = GetNActiveBins(dim) + 1;
     403           0 :   selectBins[dim] = new Short_t[nBins];
     404             :   
     405             :   // select/unselect all bins
     406           0 :   Bool_t containsAny = ContainsAny(dim);
     407           0 :   if (include || (containsAny && !displayed)) {
     408           0 :     memset(selectBins[dim], 0, sizeof(Short_t) * nBins);
     409           0 :     if (!include) selectBins[dim][FindBin(dim, "ANY", kFALSE)] = 1;
     410           0 :   } else for (Int_t j=0; j<nBins; j++) selectBins[dim][j] = 1;
     411             :   
     412             :   // select/unselect specific key words
     413             :   TObjString* key = 0x0;
     414           0 :   TIter nextKey(keys);
     415           0 :   while ((key = static_cast<TObjString*>(nextKey()))) {
     416             :     
     417             :     // special case of key word "ANY"
     418           0 :     if (key->String() == "ANY") {
     419             :       
     420           0 :       if (containsAny) {
     421             :         
     422           0 :         Int_t binAny = FindBin(dim, "ANY", kFALSE);
     423           0 :         if (include) selectBins[dim][binAny] = 1;
     424           0 :         else selectBins[dim][binAny] = 0;
     425             :         
     426           0 :       } else {
     427             :         
     428           0 :         if (include) for (Int_t j=0; j<nBins; j++) selectBins[dim][j] = 1;
     429           0 :         else memset(selectBins[dim], 0, sizeof(Short_t) * nBins);
     430             :         
     431             :       }
     432             :       
     433             :     } else { // other cases
     434             :       
     435             :       // find the corresponding bin
     436           0 :       Int_t bin = FindBin(dim, key->String().Data(), kFALSE);
     437           0 :       if (bin < 0) {
     438           0 :         delete keys;
     439           0 :         return kFALSE;
     440             :       }
     441             :       
     442             :       // select/unselect it
     443           0 :       if (include) selectBins[dim][bin] = 1;
     444           0 :       else if (containsAny && !displayed) selectBins[dim][bin] = -1;
     445           0 :       else selectBins[dim][bin] = 0;
     446             :       
     447           0 :     }
     448             :     
     449             :   }
     450             :   
     451             :   // clean memory
     452           0 :   delete keys;
     453             :   
     454           0 :   return kTRUE;
     455           0 : }
     456             : 
     457             : //-----------------------------------------------------------------------
     458             : void AliCounterCollection::CleanListOfStrings(TObjArray* list)
     459             : {
     460             :   /// Make sure all strings appear only once in this list
     461             :   
     462             :   // remove multiple-occurrence
     463           0 :   Int_t nEntries = list->GetEntriesFast();
     464           0 :   for (Int_t i = 0; i < nEntries; i++) {
     465           0 :     TObjString* entry1 = static_cast<TObjString*>(list->UncheckedAt(i));
     466           0 :     if (!entry1) continue;
     467           0 :     for (Int_t j = i+1; j < nEntries; j++) {
     468           0 :       TObjString* entry2 = static_cast<TObjString*>(list->UncheckedAt(j));
     469           0 :       if (entry2 && entry2->IsEqual(entry1)) {
     470           0 :         AliWarning(Form("multiple-occurence of string \"%s\" --> removed",entry2->String().Data()));
     471           0 :         list->RemoveAt(j);
     472           0 :       }
     473             :     }
     474           0 :   }
     475             :   
     476             :   // remove empty slots
     477           0 :   list->Compress();
     478           0 : }
     479             : 
     480             : //-----------------------------------------------------------------------
     481             : void AliCounterCollection::Count(TString externalKey, Int_t value)
     482             : {
     483             :   /// Add "value" to the counter referenced by "externalKey".
     484             :   /// The externalKey format must be rubric:keyWord/rubric:keyWord/rubric:keyWord/...
     485           0 :   if (value > 0) CountAsDouble(externalKey, (Double_t)value);
     486           0 :   else if (value < 0) AliError("cannot count negative values");
     487           0 : }
     488             : 
     489             : //-----------------------------------------------------------------------
     490             : void AliCounterCollection::Count(TString externalKey, Double_t value)
     491             : {
     492             :   /// Add "value" to the counter referenced by "externalKey".
     493             :   /// The externalKey format must be rubric:keyWord/rubric:keyWord/rubric:keyWord/...
     494           0 :   if (fWeightedCounters) CountAsDouble(externalKey, value);
     495           0 :   else AliError("non-weighted counters can only be filled with intergers");
     496           0 : }
     497             : 
     498             : //-----------------------------------------------------------------------
     499             : void AliCounterCollection::CountAsDouble(TString externalKey, Double_t value)
     500             : {
     501             :   /// Add "value" to the counter referenced by "externalKey".
     502             :   /// The externalKey format must be rubric:keyWord/rubric:keyWord/rubric:keyWord/...
     503             :   
     504           0 :   if (!fCounters) {
     505           0 :     AliError("counters are not initialized");
     506           0 :     return;
     507             :   }
     508             :   
     509           0 :   externalKey.ToUpper();
     510             :   
     511             :   // convert external to internal key
     512           0 :   Int_t nEmptySlots = 0;
     513           0 :   const Int_t* bins = FindBins(externalKey, kTRUE, nEmptySlots);
     514           0 :   if (!bins) return;
     515             :   
     516             :   // check for empty slots
     517           0 :   if (nEmptySlots > 0) {
     518           0 :     AliError("incomplete key");
     519           0 :     delete[] bins;
     520           0 :     return;
     521             :   }
     522             :   
     523           0 :   if (fWeightedCounters || fLongCounters) {
     524             :     
     525             :     // increment the corresponding counter
     526           0 :     fCounters->AddBinContent(bins, value);
     527             :     
     528           0 :   } else {
     529             :     
     530             :     // switch to long counters if needed before incrementing
     531           0 :     Long64_t linBin = fCounters->GetBin(bins, kTRUE);
     532           0 :     Double_t currentValue = fCounters->GetBinContent(linBin);
     533           0 :     if (currentValue+value > INT_MAX) {
     534           0 :       ConvertToTHnSparseL(fCounters);
     535           0 :       fLongCounters = kTRUE;
     536           0 :       fCounters->AddBinContent(bins, value);
     537           0 :     } else fCounters->AddBinContent(linBin, value);
     538             :     
     539             :   }
     540             :   
     541             :   // clean memory
     542           0 :   delete[] bins;
     543           0 : }
     544             : 
     545             : //-----------------------------------------------------------------------
     546             : void AliCounterCollection::Print(const Option_t* opt) const
     547             : {
     548             :   /// Print every individual counters if opt=="" or call "Print(opt, "")".
     549             :   
     550           0 :   if (strcmp(opt,"")) {
     551           0 :     const_cast<AliCounterCollection*>(this)->Print(opt, "");
     552           0 :     return;
     553             :   }
     554             :   
     555           0 :   if (!fCounters) {
     556           0 :     AliError("counters are not initialized");
     557           0 :     return;
     558             :   }
     559             :   
     560           0 :   if (fCounters->GetNbins() == 0) {
     561           0 :     printf("\nall counters are empty\n\n");
     562           0 :     return;
     563             :   }
     564             :   
     565           0 :   Int_t nRubrics = fCounters->GetNdimensions();
     566           0 :   Int_t* bins = new Int_t[nRubrics];
     567             :   
     568             :   // loop over every filled counters
     569           0 :   for (Long64_t i=0; i<fCounters->GetNbins(); ++i) {
     570             :     
     571             :     // get the content of the bin
     572           0 :     Double_t value = fCounters->GetBinContent(i, bins);
     573             :     
     574             :     // build the corresponding counter name
     575           0 :     TString counter;
     576           0 :     for (Int_t j=0; j<nRubrics; j++) counter += Form("/%s",fCounters->GetAxis(j)->GetBinLabel(bins[j]));
     577           0 :     counter += "/";
     578             :     
     579             :     // print value
     580           0 :     if (fWeightedCounters) printf("\n%s   %g", counter.Data(), value);
     581           0 :     else if (fLongCounters) printf("\n%s   %ld", counter.Data(), (Long_t)value);
     582           0 :     else printf("\n%s   %d", counter.Data(), (Int_t)value);
     583           0 :   }
     584           0 :   printf("\n\n");
     585             :   
     586             :   // clean memory
     587           0 :   delete[] bins;
     588           0 : }
     589             : 
     590             : //-----------------------------------------------------------------------
     591             : TString AliCounterCollection::GetKeyWords(TString rubric) const
     592             : {
     593             :   /// return the list of key words for the given rubric.
     594             :   
     595           0 :   TString keyWords = "";
     596             :   
     597           0 :   if (!fCounters) {
     598           0 :     AliError("counters are not initialized");
     599           0 :     return keyWords;
     600             :   }
     601             :   
     602           0 :   rubric.ToUpper();
     603             :   
     604             :   // get the dimension corresponding to that rubric
     605           0 :   Int_t dim = FindDim(rubric);
     606           0 :   if (dim < 0) return keyWords;
     607             :   
     608             :   // build list of key words
     609             :   TObjString* label = 0x0;
     610           0 :   TIter nextLabel(fCounters->GetAxis(dim)->GetLabels());
     611           0 :   while ((label = static_cast<TObjString*>(nextLabel()))) keyWords += Form("%s,",label->String().Data());
     612           0 :   keyWords.Remove(TString::kTrailing, ',');
     613             :   
     614             :   return keyWords;
     615           0 : }
     616             : 
     617             : //-----------------------------------------------------------------------
     618             : Double_t AliCounterCollection::GetSum(TString selections, Bool_t* longCounters)
     619             : {
     620             :   /// Get the overall statistics for the given selection (result is integrated over not specified rubrics):
     621             :   /// - format of "selections" is rubric:[any-]keyWord,keyWord,../rubric:[any-]keyWord,.. (order does not matter).
     622             :   /// - The flag "longCounters" tells whether the histogram contains value(s) larger than INT_MAX.
     623             :   
     624             :   // set the flag "longCounters" according to the content of current counters
     625           0 :   if (longCounters) *longCounters = fLongCounters;
     626             :   
     627           0 :   if (!fCounters) {
     628           0 :     AliError("counters are not initialized");
     629           0 :     return 0.;
     630             :   }
     631             :   
     632           0 :   selections.ToUpper();
     633             :   
     634             :   // decode the selections
     635           0 :   Short_t** select = DecodeSelection(selections, TObjArray());
     636           0 :   if (!select) return 0.;
     637             :   
     638             :   // loop over every filled counters and compute integral
     639             :   Double_t sum = 0.;
     640           0 :   Int_t nDims = fCounters->GetNdimensions();
     641           0 :   Int_t* coord = new Int_t[nDims];
     642           0 :   for (Long64_t i=0; i<fCounters->GetNbins(); ++i) {
     643             :     
     644             :     // get the content of the counter
     645           0 :     Double_t value = fCounters->GetBinContent(i, coord);
     646             :     
     647             :     // discard not selected counters and compute the selection factor
     648             :     Int_t selectionFactor = 1;
     649           0 :     for (Int_t dim = 0; dim < nDims && selectionFactor != 0; dim++) selectionFactor *= select[dim][coord[dim]];
     650           0 :     if (selectionFactor == 0) continue;
     651             :     
     652             :     // compute integral
     653           0 :     sum += selectionFactor * value;
     654           0 :   }
     655             :   
     656             :   // check if the sum exceed INT_MAX (only in case of integer counters)
     657           0 :   if (longCounters && !fWeightedCounters && sum > INT_MAX) *longCounters = kTRUE;
     658             :   
     659             :   // clean memory
     660           0 :   for (Int_t iDim=0; iDim<nDims; iDim++) delete[] select[iDim];
     661           0 :   delete[] select;
     662           0 :   delete[] coord;
     663             :   
     664             :   return sum;
     665           0 : }
     666             : 
     667             : //-----------------------------------------------------------------------
     668             : void AliCounterCollection::PrintKeyWords() const
     669             : {
     670             :   /// Print the full list of key words.
     671             :   
     672           0 :   if (!fCounters) {
     673           0 :     AliError("counters are not initialized");
     674           0 :     return;
     675             :   }
     676             :   
     677             :   // loop over rubrics
     678           0 :   Int_t nRubrics = fCounters->GetNdimensions();
     679           0 :   for (Int_t iDim=0; iDim<nRubrics; iDim++) {
     680           0 :     TAxis* axis = fCounters->GetAxis(iDim);
     681             :     
     682             :     // print rubric's name
     683           0 :     printf("\n%s:", axis->GetName());
     684             :     
     685             :     // loop over key words
     686             :     Bool_t first = kTRUE;
     687             :     TObjString* label = 0x0;
     688           0 :     TIter nextLabel(axis->GetLabels());
     689           0 :     while ((label = static_cast<TObjString*>(nextLabel()))) {
     690             :       
     691             :       //print key word's name
     692           0 :       if (first) {
     693           0 :         printf("%s", label->String().Data());
     694             :         first = kFALSE;
     695           0 :       } else printf(",%s", label->String().Data());
     696             :       
     697             :     }
     698           0 :   }
     699           0 :   printf("\n\n");
     700           0 : }
     701             : 
     702             : //-----------------------------------------------------------------------
     703             : void AliCounterCollection::PrintValue(TString selections)
     704             : {
     705             :   /// Print value of selected counter.
     706             :   /// format of "selections" is rubric:keyWord/rubric:keyWord/rubric:keyWord/...
     707             :   
     708           0 :   if (!fCounters) {
     709           0 :     AliError("counters are not initialized");
     710           0 :     return;
     711             :   }
     712             :   
     713           0 :   selections.ToUpper();
     714             :   
     715             :   // convert external to internal key
     716           0 :   Int_t nEmptySlots = 0;
     717           0 :   const Int_t* selectedBins = FindBins(selections, kFALSE, nEmptySlots);
     718           0 :   if (!selectedBins) return;
     719             :   
     720             :   // check for empty slots
     721           0 :   if (nEmptySlots > 0) {
     722           0 :     AliError("incomplete key");
     723           0 :     delete[] selectedBins;
     724           0 :     return;
     725             :   }
     726             :   
     727             :   // print value
     728           0 :   if (fWeightedCounters) printf("\n%g\n\n", fCounters->GetBinContent(selectedBins));
     729           0 :   else if (fLongCounters) printf("\n%ld\n\n", (Long_t) fCounters->GetBinContent(selectedBins));
     730           0 :   else printf("\n%d\n\n", (Int_t) fCounters->GetBinContent(selectedBins));
     731             :   
     732             :   // clean memory
     733           0 :   delete[] selectedBins;
     734           0 : }
     735             : 
     736             : //-----------------------------------------------------------------------
     737             : void AliCounterCollection::Print(TString rubrics, TString selections, Bool_t removeEmpty)
     738             : {
     739             :   /// Print desired rubrics for the given selection:
     740             :   /// - format of "rubrics" is rubric1/rubric2/.. (order matters only for output).
     741             :   /// - format of "selections" is rubric:[any-]keyWord,keyWord,../rubric:[any-]keyWord,.. (order does not matter).
     742             :   /// If "data" contains 1 rubric, the output will be one counter for each element of that rubric.
     743             :   /// If "data" contains 2 rubrics, the output will be an array of counters, rubric1 vs rubric2.
     744             :   /// If "data" contains 3 rubrics, the output will be an array rubric1 vs rubric2 for each element in rubric3.
     745             :   /// ...
     746             :   /// Results are integrated over rubrics not specified neither in "rubrics" nor in "selections".
     747             :   
     748           0 :   if (!fCounters) {
     749           0 :     AliError("counters are not initialized");
     750           0 :     return;
     751             :   }
     752             :   
     753           0 :   rubrics.ToUpper();
     754           0 :   selections.ToUpper();
     755             :   
     756             :   // get the rubrics to print
     757           0 :   TObjArray* rubricsToPrint = rubrics.Tokenize("/");
     758           0 :   if (rubricsToPrint->GetEntriesFast() == 0) {
     759           0 :     delete rubricsToPrint;
     760           0 :     return;
     761             :   }
     762             :   
     763             :   // remove rubrics called twice
     764           0 :   CleanListOfStrings(rubricsToPrint);
     765             :   
     766             :   // project counters in the rubrics to print according to the selections
     767           0 :   Bool_t longCounters = kFALSE;
     768           0 :   TObject* hist = Projection(*rubricsToPrint, selections, longCounters);
     769           0 :   if (!hist) {
     770           0 :     delete rubricsToPrint;
     771           0 :     return;
     772             :   }
     773             :   
     774             :   // print counters
     775           0 :   Int_t nRubricsToPrint = rubricsToPrint->GetEntriesFast();
     776           0 :   if (nRubricsToPrint == 1 && (static_cast<TH1D*>(hist))->GetEntries() > 0)
     777           0 :     PrintList(static_cast<TH1D*>(hist), removeEmpty, longCounters);
     778           0 :   else if (nRubricsToPrint == 2 && (static_cast<TH2D*>(hist))->GetEntries() > 0)
     779           0 :     PrintArray(static_cast<TH2D*>(hist), removeEmpty, longCounters);
     780           0 :   else if (nRubricsToPrint > 2 && (static_cast<THnSparse*>(hist))->GetEntries() > 0)
     781           0 :     PrintListOfArrays(static_cast<THnSparse*>(hist), removeEmpty, longCounters);
     782             :   else
     783           0 :     printf("\nselected counters are empty\n\n");
     784             :   
     785             :   // clean memory
     786           0 :   delete rubricsToPrint;
     787           0 :   delete hist;
     788           0 : }
     789             : 
     790             : //-----------------------------------------------------------------------
     791             : void AliCounterCollection::PrintSum(TString selections)
     792             : {
     793             :   /// Print the overall statistics for the given selection (result is integrated over not specified rubrics):
     794             :   /// - format of "selections" is rubric:[any-]keyWord,keyWord,../rubric:[any-]keyWord,.. (order does not matter).
     795           0 :   Bool_t longCounters = kFALSE;
     796           0 :   Double_t sum = GetSum(selections, &longCounters);
     797           0 :   if (fWeightedCounters) printf("\n%g\n\n", sum);
     798           0 :   else if (longCounters) printf("\n%ld\n\n", (Long_t)sum);
     799           0 :   else printf("\n%d\n\n", (Int_t)sum);
     800           0 : }
     801             : 
     802             : //-----------------------------------------------------------------------
     803             : void AliCounterCollection::PrintList(const TH1D* hist, Bool_t removeEmpty, Bool_t longCounters) const
     804             : {
     805             :   /// Print the content of 1D histogram as a list.
     806             :   
     807             :   // set the format to print labels
     808           0 :   THashList* labels = hist->GetXaxis()->GetLabels();
     809           0 :   TString format = "";
     810           0 :   if (fWeightedCounters) format = Form("\n%%%ds %%10g",GetMaxLabelSize(labels));
     811           0 :   else if (longCounters) format = Form("\n%%%ds %%16ld",GetMaxLabelSize(labels));
     812           0 :   else format = Form("\n%%%ds %%10d",GetMaxLabelSize(labels));
     813             :   
     814             :   // print value for each label
     815             :   TObjString* label = 0x0;
     816           0 :   TIter nextLabel(labels);
     817           0 :   while ((label = static_cast<TObjString*>(nextLabel()))) {
     818           0 :     Int_t bin = (Int_t) label->GetUniqueID();
     819           0 :     Double_t value = hist->GetBinContent(bin);
     820           0 :     if (removeEmpty && value == 0.) continue;
     821           0 :     if (fWeightedCounters) printf(format.Data(), label->String().Data(), value);
     822           0 :     else if (longCounters) printf(format.Data(), label->String().Data(), (Long_t) value);
     823           0 :     else printf(format.Data(), label->String().Data(), (Int_t) value);
     824           0 :   }
     825           0 :   printf("\n\n");
     826           0 : }
     827             : 
     828             : //-----------------------------------------------------------------------
     829             : void AliCounterCollection::PrintArray(const TH2D* hist, Bool_t removeEmpty, Bool_t longCounters) const
     830             : {
     831             :   /// Print the content of 2D histogram as an array.
     832             :   
     833             :   // set the format to print labels in X direction
     834           0 :   THashList* labelsX = hist->GetXaxis()->GetLabels();
     835           0 :   TString formatX(Form("\n%%%ds ",GetMaxLabelSize(labelsX)));
     836             :   
     837             :   // set the format to print labels in Y direction
     838           0 :   THashList* labelsY = hist->GetYaxis()->GetLabels();
     839           0 :   Int_t maxLabelSizeY = GetMaxLabelSize(labelsY);
     840           0 :   TString formatYv = "";
     841           0 :   if (fWeightedCounters) {
     842           0 :     maxLabelSizeY = TMath::Max(10, maxLabelSizeY);
     843           0 :     formatYv = Form("%%%dg ",maxLabelSizeY);
     844           0 :   } else if (longCounters) {
     845           0 :     maxLabelSizeY = TMath::Max(16, maxLabelSizeY);
     846           0 :     formatYv = Form("%%%dld ",maxLabelSizeY);
     847             :   } else {
     848           0 :     maxLabelSizeY = TMath::Max(10, maxLabelSizeY);
     849           0 :     formatYv = Form("%%%dd ",maxLabelSizeY);
     850             :   }
     851           0 :   TString formatYs = Form("%%%ds ",maxLabelSizeY);
     852             :   
     853             :   // if required, set the list of labels for which all counters are not empty
     854             :   Bool_t *useLabelX = 0x0, *useLabelY = 0x0;
     855             :   TObjString *labelX = 0x0, *labelY = 0x0;
     856           0 :   TIter nextLabelX(labelsX);
     857           0 :   TIter nextLabelY(labelsY);
     858           0 :   if (removeEmpty) {
     859             :     
     860             :     // create label flags and set them as unused
     861           0 :     useLabelX = new Bool_t[labelsX->GetSize()+1];
     862           0 :     memset(useLabelX, kFALSE, sizeof(Bool_t) * (labelsX->GetSize()+1));
     863           0 :     useLabelY = new Bool_t[labelsY->GetSize()+1];
     864           0 :     memset(useLabelY, kFALSE, sizeof(Bool_t) * (labelsY->GetSize()+1));
     865             :     
     866             :     // loop over labels in X direction
     867           0 :     while ((labelX = static_cast<TObjString*>(nextLabelX()))) {
     868           0 :       Int_t binX = (Int_t) labelX->GetUniqueID();
     869             :       
     870             :       // loop over labels in Y direction
     871           0 :       nextLabelY.Reset();
     872           0 :       while ((labelY = static_cast<TObjString*>(nextLabelY()))) {
     873           0 :         Int_t binY = (Int_t) labelY->GetUniqueID();
     874             :         
     875             :         // both labels already set as used
     876           0 :         if (useLabelX[binX] && useLabelY[binY]) continue;
     877             :         
     878             :         // skip empty bins
     879           0 :         if (hist->GetBinContent(binX, binY) == 0.) continue;
     880             :         
     881             :         // set label as used
     882           0 :         useLabelX[binX] = kTRUE;
     883           0 :         useLabelY[binY] = kTRUE;
     884             :         
     885           0 :       }
     886             :       
     887             :     }
     888             :     
     889             :   }
     890             :   
     891             :   // print labels in Y axis
     892           0 :   printf(formatX.Data()," ");
     893           0 :   nextLabelY.Reset();
     894           0 :   while ((labelY = static_cast<TObjString*>(nextLabelY()))) {
     895           0 :     if (removeEmpty && !useLabelY[labelY->GetUniqueID()]) continue;
     896           0 :     printf(formatYs.Data(), labelY->String().Data());
     897             :   }
     898             :   
     899             :   // fill array for each label in X axis
     900           0 :   nextLabelX.Reset();
     901           0 :   while ((labelX = static_cast<TObjString*>(nextLabelX()))) {
     902           0 :     Int_t binX = (Int_t) labelX->GetUniqueID();
     903             :     
     904           0 :     if (removeEmpty && !useLabelX[binX]) continue;
     905             :     
     906             :     // print label X
     907           0 :     printf(formatX.Data(), labelX->String().Data());
     908             :     
     909             :     // print value for each label in Y axis
     910           0 :     nextLabelY.Reset();
     911           0 :     while ((labelY = static_cast<TObjString*>(nextLabelY()))) {
     912           0 :       Int_t binY = (Int_t) labelY->GetUniqueID();
     913           0 :       if (removeEmpty && !useLabelY[binY]) continue;
     914           0 :       if (fWeightedCounters) printf(formatYv.Data(), hist->GetBinContent(binX, binY));
     915           0 :       else if (longCounters) printf(formatYv.Data(), (Long_t) hist->GetBinContent(binX, binY));
     916           0 :       else printf(formatYv.Data(), (Int_t) hist->GetBinContent(binX, binY));
     917           0 :     }
     918           0 :   }
     919           0 :   printf("\n\n");
     920             :   
     921             :   // clean memory
     922           0 :   if (removeEmpty) {
     923           0 :     delete[] useLabelX;
     924           0 :     delete[] useLabelY;
     925             :   }
     926           0 : }
     927             : 
     928             : //-----------------------------------------------------------------------
     929             : void AliCounterCollection::PrintListOfArrays(const THnSparse* hist, Bool_t removeEmpty, Bool_t longCounters) const
     930             : {
     931             :   /// Print the content of nD histogram as a list of arrays.
     932             :   
     933             :   // set the format to print labels in X direction
     934           0 :   THashList* labelsX = hist->GetAxis(0)->GetLabels();
     935           0 :   TString formatX(Form("\n%%%ds ",GetMaxLabelSize(labelsX)));
     936             :   
     937             :   // set the format to print labels in Y direction
     938           0 :   THashList* labelsY = hist->GetAxis(1)->GetLabels();
     939           0 :   Int_t maxLabelSizeY = GetMaxLabelSize(labelsY);
     940           0 :   TString formatYv = "";
     941           0 :   if (fWeightedCounters) {
     942           0 :     maxLabelSizeY = TMath::Max(10, maxLabelSizeY);
     943           0 :     formatYv = Form("%%%dg ",maxLabelSizeY);
     944           0 :   } else if (longCounters) {
     945           0 :     maxLabelSizeY = TMath::Max(16, maxLabelSizeY);
     946           0 :     formatYv = Form("%%%dld ",maxLabelSizeY);
     947             :   } else {
     948           0 :     maxLabelSizeY = TMath::Max(10, maxLabelSizeY);
     949           0 :     formatYv = Form("%%%dd ",maxLabelSizeY);
     950             :   }
     951           0 :   TString formatYs(Form("%%%ds ",maxLabelSizeY));
     952             :   
     953             :   // create a list containing each combination of labels refering the arrays to be printout
     954           0 :   TList listOfCombis;
     955           0 :   listOfCombis.SetOwner();
     956             :   
     957             :   // add a first empty combination
     958           0 :   Int_t nDim = hist->GetNdimensions();
     959           0 :   listOfCombis.AddLast(new TObjArray(nDim-2));
     960             :   
     961             :   // loop over the nDim-2 other rubrics
     962           0 :   for (Int_t i=2; i<nDim; i++) {
     963             :     
     964             :     // save the last label of that rubic
     965           0 :     THashList* labels = hist->GetAxis(i)->GetLabels();
     966           0 :     TObjString* lastLabel = (labels) ? static_cast<TObjString*>(labels->Last()) : 0x0;
     967           0 :     if (!lastLabel) return;
     968             :     
     969             :     // prepare iteration over the list of labels
     970           0 :     TIter nextLabel(labels);
     971             :     
     972             :     // loop over existing combinations
     973           0 :     TObjLink* lnk = listOfCombis.FirstLink();
     974           0 :     while (lnk) {
     975             :       
     976             :       // get the current combination
     977           0 :       TObjArray* currentCombi = static_cast<TObjArray*>(lnk->GetObject());
     978             :       
     979             :       // loop over labels in the current rubric
     980           0 :       nextLabel.Reset();
     981             :       TObjString* label = 0x0;
     982           0 :       while ((label = static_cast<TObjString*>(nextLabel()))) {
     983             :         
     984             :         // stop at the last one
     985           0 :         if (label == lastLabel) break;
     986             :         
     987             :         // copy the current combination, add the current label to it and add it to the list of combinations
     988           0 :         TObjArray* combi = new TObjArray(*currentCombi);
     989           0 :         combi->AddLast(label);
     990           0 :         listOfCombis.AddBefore(lnk, combi);
     991             :       }
     992             :       
     993             :       // add the last label to the current combination
     994           0 :       currentCombi->AddLast(lastLabel);
     995             :       
     996           0 :       lnk = lnk->Next();
     997             :     }
     998             :     
     999           0 :   }
    1000             :   
    1001             :   // create bin coordinates to access individual counters
    1002           0 :   Int_t* bins = new Int_t[nDim];
    1003             :   
    1004             :   // create label flags
    1005             :   Bool_t *useLabelX = 0x0, *useLabelY = 0x0;
    1006           0 :   if (removeEmpty) {
    1007           0 :     useLabelX = new Bool_t[labelsX->GetSize()+1];
    1008           0 :     useLabelY = new Bool_t[labelsY->GetSize()+1];
    1009           0 :   }
    1010             :   
    1011             :   // loop over each combination of labels
    1012             :   TObjArray* combi = 0x0;
    1013           0 :   TIter nextCombi(&listOfCombis);
    1014           0 :   while ((combi = static_cast<TObjArray*>(nextCombi()))) {
    1015             :     
    1016             :     // make the name of the combination and fill the corresponding bin coordinates
    1017           0 :     TString combiName = "/";
    1018           0 :     for (Int_t i=2; i<nDim; i++) {
    1019           0 :       TObjString* label = static_cast<TObjString*>(combi->UncheckedAt(i-2));
    1020           0 :       combiName += Form("%s/",label->String().Data());
    1021           0 :       bins[i] = (Int_t)label->GetUniqueID();
    1022             :     }
    1023             :     
    1024             :     // reset the list of labels for which all counters are not empty
    1025           0 :     if (removeEmpty) {
    1026           0 :       memset(useLabelX, kFALSE, sizeof(Bool_t) * (labelsX->GetSize()+1));
    1027           0 :       memset(useLabelY, kFALSE, sizeof(Bool_t) * (labelsY->GetSize()+1));
    1028           0 :     }
    1029             :     
    1030             :     Bool_t empty = kTRUE;
    1031             :     TObjString* labelX = 0x0;
    1032             :     TObjString* labelY = 0x0;
    1033           0 :     TIter nextLabelX(labelsX);
    1034           0 :     TIter nextLabelY(labelsY);
    1035             :     // loop over labels in X direction
    1036           0 :     while ((labelX = static_cast<TObjString*>(nextLabelX()))) {
    1037           0 :       bins[0] = (Int_t) labelX->GetUniqueID();
    1038             :       
    1039             :       // loop over labels in Y direction
    1040           0 :       nextLabelY.Reset();
    1041           0 :       while ((labelY = static_cast<TObjString*>(nextLabelY()))) {
    1042           0 :         bins[1] = (Int_t) labelY->GetUniqueID();
    1043             :         
    1044             :         // both labels already set as used
    1045           0 :         if (removeEmpty && useLabelX[bins[0]] && useLabelY[bins[1]]) continue;
    1046             :         
    1047             :         // skip empty bins
    1048           0 :         if (hist->GetBinContent(bins) == 0.) continue;
    1049             :         
    1050             :         // set label as used and array as not empty
    1051             :         empty = kFALSE;
    1052           0 :         if (removeEmpty) {
    1053           0 :           useLabelX[bins[0]] = kTRUE;
    1054           0 :           useLabelY[bins[1]] = kTRUE;
    1055             :         } else break;
    1056             :         
    1057             :       }
    1058             :       
    1059           0 :       if (!removeEmpty && !empty) break;
    1060             :       
    1061             :     }
    1062             :     
    1063             :     // skip empty arrays
    1064           0 :     if (empty) continue;
    1065             :     
    1066             :     // print the name of the combination of labels refering the incoming array
    1067           0 :     printf("\n%s:\n",combiName.Data());
    1068             :     
    1069             :     // print labels in Y axis
    1070           0 :     printf(formatX.Data()," ");
    1071           0 :     nextLabelY.Reset();
    1072           0 :     while ((labelY = static_cast<TObjString*>(nextLabelY()))) {
    1073           0 :       if (removeEmpty && !useLabelY[labelY->GetUniqueID()]) continue;
    1074           0 :       printf(formatYs.Data(), labelY->String().Data());
    1075             :     }
    1076             :     
    1077             :     // fill array for each label in X axis
    1078           0 :     nextLabelX.Reset();
    1079           0 :     while ((labelX = static_cast<TObjString*>(nextLabelX()))) {
    1080           0 :       bins[0] = (Int_t) labelX->GetUniqueID();
    1081             :       
    1082           0 :       if (removeEmpty && !useLabelX[bins[0]]) continue;
    1083             :       
    1084             :       // print label X
    1085           0 :       printf(formatX.Data(), labelX->String().Data());
    1086             :       
    1087             :       // print value for each label in Y axis
    1088           0 :       nextLabelY.Reset();
    1089           0 :       while ((labelY = static_cast<TObjString*>(nextLabelY()))) {
    1090           0 :         bins[1] = (Int_t) labelY->GetUniqueID();
    1091           0 :         if (removeEmpty && !useLabelY[bins[1]]) continue;
    1092           0 :         if (fWeightedCounters) printf(formatYv.Data(), hist->GetBinContent(bins));
    1093           0 :         else if (longCounters) printf(formatYv.Data(), (Long_t) hist->GetBinContent(bins));
    1094           0 :         else printf(formatYv.Data(), (Int_t) hist->GetBinContent(bins));
    1095             :       }
    1096             :     }
    1097           0 :     printf("\n\n");
    1098           0 :   }
    1099             :   
    1100             :   // clean memory
    1101           0 :   delete[] bins;
    1102           0 :   if (removeEmpty) {
    1103           0 :     delete[] useLabelX;
    1104           0 :     delete[] useLabelY;
    1105             :   }
    1106           0 : }
    1107             : 
    1108             : //-----------------------------------------------------------------------
    1109             : Int_t AliCounterCollection::GetMaxLabelSize(THashList* labels) const
    1110             : {
    1111             :   /// Return the number of characters of the longest label.
    1112             :   Int_t maxLabelSize = 0;
    1113             :   TObjString* label = 0x0;
    1114           0 :   TIter nextLabel(labels);
    1115           0 :   while ((label = static_cast<TObjString*>(nextLabel())))
    1116           0 :     maxLabelSize = TMath::Max(maxLabelSize, label->String().Length());
    1117             :   return maxLabelSize;
    1118           0 : }
    1119             : 
    1120             : //-----------------------------------------------------------------------
    1121             : TH1D* AliCounterCollection::Get(TString rubric, TString selections)
    1122             : {
    1123             :   /// Get counters of the rubric "rubric" for the given "selection".
    1124             :   /// Format of "selections" is rubric:[any-]keyWord,keyWord,../rubric:[any-]keyWord,.. (order does not matter).
    1125             :   /// Results are integrated over rubrics not specified neither in "rubric1" nor in "selections".
    1126             :   /// It is the responsability of the user to delete the returned histogram.
    1127             :   
    1128           0 :   if (!fCounters) {
    1129           0 :     AliError("counters are not initialized");
    1130           0 :     return 0x0;
    1131             :   }
    1132             :   
    1133           0 :   rubric.ToUpper();
    1134           0 :   selections.ToUpper();
    1135             :   
    1136             :   // fill the rubrics to print
    1137           0 :   TObjArray rubricsToPrint(1);
    1138           0 :   rubricsToPrint.SetOwner();
    1139           0 :   rubricsToPrint.AddLast(new TObjString(rubric.Data()));
    1140             :   
    1141             :   // project counters in the rubrics to print according to the selections
    1142           0 :   Bool_t longCounters = kFALSE;
    1143           0 :   TH1D* hist = static_cast<TH1D*>(Projection(rubricsToPrint, selections, longCounters));
    1144             :   
    1145             :   // make it ready to display
    1146           0 :   if (hist) {
    1147             :     
    1148             :     // remove statistic box
    1149           0 :     hist->SetStats(kFALSE);
    1150             :     
    1151             :     // prepare X axis
    1152           0 :     TAxis* axis = hist->GetXaxis();
    1153           0 :     THashList* labels = axis->GetLabels();
    1154           0 :     Int_t nLabels = (labels) ? labels->GetSize() : 1;
    1155           0 :     axis->SetRange(1,nLabels);
    1156           0 :     axis->SetNdivisions(1,kFALSE);
    1157           0 :     axis->SetTitle(rubric.Data());
    1158             :     
    1159             :     // prepare Y axis
    1160           0 :     hist->GetYaxis()->SetTitle("Counts");
    1161           0 :   }
    1162             :   
    1163             :   return hist;
    1164           0 : }
    1165             : 
    1166             : //-----------------------------------------------------------------------
    1167             : TH2D* AliCounterCollection::Get(TString rubric1, TString rubric2, TString selections)
    1168             : {
    1169             :   /// Get counters of the "rubric1" vs "rubric2" for the given "selection".
    1170             :   /// Format of "selections" is rubric:[any-]keyWord,keyWord,../rubric:[any-]keyWord,.. (order does not matter).
    1171             :   /// Results are integrated over rubrics not specified neither in "rubric1", "rubric2" nor in "selections".
    1172             :   /// It is the responsability of the user to delete the returned histogram.
    1173             :   
    1174           0 :   if (!fCounters) {
    1175           0 :     AliError("counters are not initialized");
    1176           0 :     return 0x0;
    1177             :   }
    1178             :   
    1179           0 :   rubric1.ToUpper();
    1180           0 :   rubric2.ToUpper();
    1181           0 :   selections.ToUpper();
    1182             :   
    1183             :   // fill the rubrics to print
    1184           0 :   TObjArray rubricsToPrint(2);
    1185           0 :   rubricsToPrint.SetOwner();
    1186           0 :   rubricsToPrint.AddLast(new TObjString(rubric2.Data()));
    1187           0 :   rubricsToPrint.AddLast(new TObjString(rubric1.Data()));
    1188             :   
    1189             :   // project counters in the rubrics to print according to the selections
    1190           0 :   Bool_t longCounters = kFALSE;
    1191           0 :   TH2D* hist = static_cast<TH2D*>(Projection(rubricsToPrint, selections, longCounters));
    1192             :   
    1193             :   // draw counters
    1194           0 :   if (hist) {
    1195             :     
    1196             :     // remove statistic box
    1197           0 :     hist->SetStats(kFALSE);
    1198             :     
    1199             :     // prepare X axis
    1200           0 :     TAxis* axisX = hist->GetXaxis();
    1201           0 :     THashList* labelsX = axisX->GetLabels();
    1202           0 :     Int_t nLabelsX = (labelsX) ? labelsX->GetSize() : 1;
    1203           0 :     axisX->SetRange(1,nLabelsX);
    1204           0 :     axisX->SetNdivisions(1,kFALSE);
    1205           0 :     axisX->SetTitle(rubric2.Data());
    1206             :     
    1207             :     // prepare Y axis
    1208           0 :     TAxis* axisY = hist->GetYaxis();
    1209           0 :     THashList* labelsY = axisY->GetLabels();
    1210           0 :     Int_t nLabelsY = (labelsY) ? labelsY->GetSize() : 1;
    1211           0 :     axisY->SetRange(1,nLabelsY);
    1212           0 :     axisY->SetNdivisions(1,kFALSE);
    1213           0 :     axisY->SetTitle(rubric1.Data());
    1214           0 :   }
    1215             :   
    1216             :   return hist;
    1217           0 : }
    1218             : 
    1219             : //-----------------------------------------------------------------------
    1220             : TH1D* AliCounterCollection::Draw(TString rubric, TString selections)
    1221             : {
    1222             :   /// Draw counters of the rubric "rubric" for the given "selection".
    1223             :   /// Format of "selections" is rubric:[any-]keyWord,keyWord,../rubric:[any-]keyWord,.. (order does not matter).
    1224             :   /// Results are integrated over rubrics not specified neither in "rubric1" nor in "selections".
    1225             :   /// It is the responsability of the user to delete the returned histogram.
    1226           0 :   TH1D* hist = Get(rubric, selections);
    1227           0 :   if (hist) hist->Draw("htext");
    1228           0 :   return hist;
    1229           0 : }
    1230             : 
    1231             : //-----------------------------------------------------------------------
    1232             : TH2D* AliCounterCollection::Draw(TString rubric1, TString rubric2, TString selections)
    1233             : {
    1234             :   /// Draw counters of the "rubric1" vs "rubric2" for the given "selection".
    1235             :   /// Format of "selections" is rubric:[any-]keyWord,keyWord,../rubric:[any-]keyWord,.. (order does not matter).
    1236             :   /// Results are integrated over rubrics not specified neither in "rubric1", "rubric2" nor in "selections".
    1237             :   /// It is the responsability of the user to delete the returned histogram.
    1238           0 :   TH2D* hist = Get(rubric1, rubric2, selections);
    1239           0 :   if (hist) hist->Draw("text");
    1240           0 :   return hist;
    1241           0 : }
    1242             : 
    1243             : //-----------------------------------------------------------------------
    1244             : TObject* AliCounterCollection::Projection(const TObjArray& data, const TString& selections, Bool_t& longCounters)
    1245             : {
    1246             :   /// Return desired "data" for the given "selection" stored in a new histogram or 0x0 in case of failure.
    1247             :   /// The type of the histogram (TH1D, TH2D or THnSparse) depend on the number of data.
    1248             :   /// The flag "longCounters" tells whether the histogram contains value(s) larger than INT_MAX.
    1249             :   /// It is the responsability of the user to delete the returned histogram.
    1250             :   
    1251             :   // set the flag "longCounters" according to the content of current counters
    1252           0 :   longCounters = fLongCounters;
    1253             :   
    1254             :   // decode the selections
    1255           0 :   Short_t** select = DecodeSelection(selections, data);
    1256           0 :   if (!select) return 0x0;
    1257             :   
    1258             :   // define name and dimensions of projection histo
    1259           0 :   TString name(fCounters->GetName());
    1260           0 :   Int_t nDims = fCounters->GetNdimensions();
    1261           0 :   Int_t nTargetDims = data.GetEntriesFast();
    1262           0 :   TArrayI targetDims(nTargetDims);
    1263           0 :   TArrayI nNewBins(nTargetDims);
    1264           0 :   TArrayI* OldToNewCoord = new TArrayI[nTargetDims];
    1265           0 :   for (Int_t i=0; i<nTargetDims; i++) {
    1266             :     
    1267             :     // histo name
    1268           0 :     name += Form("_%s",static_cast<TObjString*>(data.UncheckedAt(i))->String().Data());
    1269             :     
    1270             :     // find target dims
    1271           0 :     targetDims[i] = FindDim(static_cast<TObjString*>(data.UncheckedAt(i))->String());
    1272             :     
    1273             :     // set number of selected bins in the target dims and make the correspondence between old and new coordinates
    1274           0 :     nNewBins[i] = 0;
    1275           0 :     if (targetDims[i] > -1) {
    1276           0 :       Int_t nBins = GetNActiveBins(targetDims[i]) + 1;
    1277           0 :       OldToNewCoord[i].Set(nBins);
    1278           0 :       for (Int_t j=1; j<nBins; j++) if (select[targetDims[i]][j] > 0) OldToNewCoord[i][j] = ++nNewBins[i];
    1279           0 :     }
    1280             :     
    1281             :     // clean memory and return 0x0 in case of problem
    1282           0 :     if (nNewBins[i] == 0) {
    1283           0 :       for (Int_t iDim=0; iDim<nDims; iDim++) delete[] select[iDim];
    1284           0 :       delete[] select;
    1285           0 :       delete[] OldToNewCoord;
    1286           0 :       return 0x0;
    1287             :     }
    1288             :     
    1289             :   }
    1290             :   
    1291             :   // define title of projection histo
    1292           0 :   TString title = "Selections:  ";
    1293           0 :   TString selectionString(selections);
    1294           0 :   selectionString.Remove(TString::kBoth, '/');
    1295           0 :   if (selectionString.Length() > 0) title += Form("%s/", selectionString.Data());
    1296             :   TObject* rub = 0x0;
    1297           0 :   TIter nextRubric(fRubrics);
    1298           0 :   while ((rub = nextRubric())) {
    1299           0 :     if (selectionString.Contains(Form("%s:",rub->GetName()))) continue;
    1300           0 :     if (data.Contains(rub->GetName())) continue;
    1301           0 :     title += Form("%s:ANY/", rub->GetName());
    1302             :   }
    1303           0 :   title.ReplaceAll("/", "  ");
    1304             :   
    1305             :   // Create new histograms
    1306             :   TObject* hist;
    1307           0 :   if (nTargetDims == 1) hist = new TH1D(name.Data(), title.Data(), nNewBins[0], 0., 1.);
    1308           0 :   else if (nTargetDims == 2) hist = new TH2D(name.Data(), title.Data(), nNewBins[0], 0., 1., nNewBins[1], 0., 1.);
    1309           0 :   else if (fWeightedCounters) hist = new THnSparseT<TArrayF>(name.Data(), title.Data(), nTargetDims, nNewBins.GetArray(), 0x0, 0x0);
    1310           0 :   else if (fLongCounters) hist = new THnSparseT<TArrayL>(name.Data(), title.Data(), nTargetDims, nNewBins.GetArray(), 0x0, 0x0);
    1311           0 :   else hist = new THnSparseT<TArrayI>(name.Data(), title.Data(), nTargetDims, nNewBins.GetArray(), 0x0, 0x0);
    1312             :   
    1313             :   // Set new axis labels
    1314             :   TObjString* label;
    1315           0 :   if (nTargetDims < 3) {
    1316             :     
    1317             :     // X axis
    1318           0 :     TIter nextLabelX(fCounters->GetAxis(targetDims[0])->GetLabels());
    1319           0 :     while ((label = static_cast<TObjString*>(nextLabelX()))) {
    1320           0 :       if (select[targetDims[0]][label->GetUniqueID()] > 0) {
    1321           0 :         static_cast<TH1*>(hist)->GetXaxis()->SetBinLabel(OldToNewCoord[0][label->GetUniqueID()], label->String().Data());
    1322             :       }
    1323             :     }
    1324             :     
    1325             :     // Y axis if any
    1326           0 :     if (nTargetDims == 2) {
    1327           0 :       TIter nextLabelY(fCounters->GetAxis(targetDims[1])->GetLabels());
    1328           0 :       while ((label = static_cast<TObjString*>(nextLabelY()))) {
    1329           0 :         if (select[targetDims[1]][label->GetUniqueID()] > 0) {
    1330           0 :           static_cast<TH1*>(hist)->GetYaxis()->SetBinLabel(OldToNewCoord[1][label->GetUniqueID()], label->String().Data());
    1331             :         }
    1332             :       }
    1333           0 :     }
    1334             :     
    1335           0 :   } else {
    1336             :     
    1337             :     // all axes
    1338           0 :     for (Int_t i=0; i<nTargetDims; i++) {
    1339           0 :       TIter nextLabel(fCounters->GetAxis(targetDims[i])->GetLabels());
    1340           0 :       while ((label = static_cast<TObjString*>(nextLabel()))) {
    1341           0 :         if (select[targetDims[i]][label->GetUniqueID()] > 0) {
    1342           0 :           static_cast<THnSparse*>(hist)->GetAxis(i)->SetBinLabel(OldToNewCoord[i][label->GetUniqueID()], label->String().Data());
    1343             :         }
    1344             :       }
    1345           0 :     }
    1346             :     
    1347             :   }
    1348             :   
    1349             :   // loop over every filled counters
    1350           0 :   Int_t* coord = new Int_t[nDims];
    1351           0 :   Int_t* newCoord = new Int_t[nTargetDims];
    1352             :   Int_t nEntries = 0;
    1353           0 :   for (Long64_t i=0; i<fCounters->GetNbins(); ++i) {
    1354             :     
    1355             :     // get the content of the counter
    1356           0 :     Double_t value = fCounters->GetBinContent(i, coord);
    1357             :     
    1358             :     // discard not selected counters and compute the selection factor
    1359             :     Int_t selectionFactor = 1;
    1360           0 :     for (Int_t dim = 0; dim < nDims && selectionFactor != 0; dim++) selectionFactor *= select[dim][coord[dim]];
    1361           0 :     if (selectionFactor == 0) continue;
    1362             :     
    1363             :     // find new coordinates in the projection histo
    1364           0 :     for (Int_t d = 0; d < nTargetDims; ++d) newCoord[d] = OldToNewCoord[d][coord[targetDims[d]]];
    1365             :     
    1366             :     // fill projection histo
    1367           0 :     if (nTargetDims < 3) {
    1368             :       
    1369           0 :       Int_t linBin = (nTargetDims == 1) ? newCoord[0] : static_cast<TH1*>(hist)->GetBin(newCoord[0], newCoord[1]);
    1370           0 :       static_cast<TH1*>(hist)->AddBinContent(linBin, selectionFactor*value);
    1371             :       
    1372             :       // check if the new value exceed INT_MAX (only in case of integer counters)
    1373           0 :       if (!fWeightedCounters && !longCounters && static_cast<TH1*>(hist)->GetBinContent(linBin) > INT_MAX)
    1374           0 :         longCounters = kTRUE;
    1375             :       
    1376           0 :     } else if (fWeightedCounters || longCounters) {
    1377             :       
    1378           0 :       static_cast<THnSparse*>(hist)->AddBinContent(newCoord, selectionFactor*value);
    1379             :       
    1380             :     } else {
    1381             :       
    1382             :       // switch to long counters if needed before filling
    1383           0 :       Long64_t linBin = static_cast<THnSparse*>(hist)->GetBin(newCoord, kTRUE);
    1384           0 :       Double_t currentValue = static_cast<THnSparse*>(hist)->GetBinContent(linBin);
    1385           0 :       if (currentValue+selectionFactor*value > INT_MAX) {
    1386           0 :         THnSparse* h = static_cast<THnSparse*>(hist);
    1387           0 :         ConvertToTHnSparseL(h);
    1388           0 :         hist = h;
    1389           0 :         longCounters = kTRUE;
    1390           0 :         static_cast<THnSparse*>(hist)->AddBinContent(newCoord, selectionFactor*value);
    1391           0 :       } else static_cast<THnSparse*>(hist)->AddBinContent(linBin, selectionFactor*value);
    1392             :       
    1393             :     }
    1394             :     
    1395           0 :     nEntries++;
    1396           0 :   }
    1397             :   
    1398             :   // update the number of entries
    1399           0 :   if (nTargetDims < 3) static_cast<TH1*>(hist)->SetEntries(nEntries);
    1400           0 :   else static_cast<THnSparse*>(hist)->SetEntries(nEntries);
    1401             :   
    1402             :   // clean memory
    1403           0 :   for (Int_t iDim=0; iDim<nDims; iDim++) delete[] select[iDim];
    1404           0 :   delete[] select;
    1405           0 :   delete[] coord;
    1406           0 :   delete[] newCoord;
    1407           0 :   delete[] OldToNewCoord;
    1408             :   
    1409             :   return hist;
    1410           0 : }
    1411             : 
    1412             : //-----------------------------------------------------------------------
    1413             : Int_t* AliCounterCollection::CheckConsistency(const AliCounterCollection* c)
    1414             : {
    1415             :   /// Consistency check of the two counter collections. To be consistent, both counters
    1416             :   /// must have the same rubrics with the same list of authorized key words if any.
    1417             :   /// Return the correspondence between the local rubric ordering and the one of the other counter,
    1418             :   /// or 0x0 in case of problem. It is the responsability of the user to delete the returned array.
    1419             :   
    1420           0 :   if (!fCounters || !c->fCounters) {
    1421           0 :     AliError("counters are not initialized");
    1422           0 :     return 0x0;
    1423             :   }
    1424             :   
    1425             :   // check if both counters are weighted or not
    1426           0 :   if (c->fWeightedCounters != fWeightedCounters) AliWarning("merging non-weighted with weigthed counters");
    1427             :   
    1428             :   // check if the number of rubrics is the same
    1429           0 :   Int_t nRubrics = fRubrics->GetSize();
    1430           0 :   if (c->fRubrics->GetSize() != nRubrics) {
    1431           0 :     AliError("both counters do not contain the same number of rubrics");
    1432           0 :     return 0x0;
    1433             :   }
    1434             :   
    1435           0 :   Int_t* otherDims = new Int_t[nRubrics];
    1436             :   
    1437             :   // loop over local rubrics
    1438             :   TObject* rubric1 = 0x0;
    1439           0 :   TIter nextRubric(fRubrics);
    1440           0 :   while ((rubric1 = nextRubric())) {
    1441             :     
    1442             :     // find that rubric in the other counter
    1443           0 :     TObject* rubric2 = c->fRubrics->FindObject(rubric1->GetName());
    1444           0 :     if (!rubric2) {
    1445           0 :       AliError(Form("the other counter does not contain the rubric %s", rubric1->GetName()));
    1446           0 :       delete[] otherDims;
    1447           0 :       return 0x0;
    1448             :     }
    1449             :     
    1450             :     // check the list of authorized key words if any
    1451           0 :     TObjArray* keyWords1 = dynamic_cast<TObjArray*>(rubric1);
    1452           0 :     TObjArray* keyWords2 = dynamic_cast<TObjArray*>(rubric2);
    1453           0 :     if (keyWords1 && keyWords2) {
    1454             :       
    1455             :       // check if the number of key words is the same
    1456           0 :       if (keyWords1->GetEntriesFast() != keyWords2->GetEntriesFast()) {
    1457           0 :         AliError("that rubric does not contain the same number of authorized key words in both counters");
    1458           0 :         delete[] otherDims;
    1459           0 :         return 0x0;
    1460             :       }
    1461             :       
    1462             :       // loop over local key words
    1463             :       TObjString* keyWord = 0x0;
    1464           0 :       TIter nextKeyWord(keyWords1);
    1465           0 :       while ((keyWord = static_cast<TObjString*>(nextKeyWord()))) {
    1466             :         
    1467             :         // find that key word in the corresponding rubric of the other counter
    1468           0 :         if (!keyWords2->FindObject(keyWord->String().Data())) {
    1469           0 :           AliError(Form("rubric %s does not contain the key word %s in the other counter", rubric1->GetName(), keyWord->String().Data()));
    1470           0 :           delete[] otherDims;
    1471           0 :           return 0x0;
    1472             :         }
    1473             :         
    1474             :       }
    1475             :       
    1476           0 :     } else if (keyWords1 || keyWords2) {
    1477             :       
    1478             :       // that rubric has not been initialized the same way in both counter
    1479           0 :       if (keyWords1) {
    1480           0 :         AliError(Form("rubric %s of the other counter does not contain a list of authorized key words while this does", rubric1->GetName()));
    1481             :       } else {
    1482           0 :         AliError(Form("rubric %s of this counter does not contain a list of authorized key words while the other does", rubric1->GetName()));
    1483             :       }
    1484           0 :       delete[] otherDims;
    1485           0 :       return 0x0;
    1486             :       
    1487             :     }
    1488             :     
    1489             :     // save the correspondence of rubric IDs in both counters
    1490           0 :     otherDims[rubric1->GetUniqueID()] = rubric2->GetUniqueID();
    1491             :     
    1492           0 :   }
    1493             :   
    1494           0 :   return otherDims;
    1495           0 : }
    1496             : 
    1497             : //-----------------------------------------------------------------------
    1498             : void AliCounterCollection::Add(const AliCounterCollection* counter)
    1499             : {
    1500             :   /// Add the given AliCounterCollections to this. They must have the
    1501             :   /// same rubrics with the same list of authorized key words if any.
    1502             :   
    1503             :   // check the consistency between the other counter and this and get the correspondences between rubric IDs.
    1504           0 :   Int_t* otherDims = CheckConsistency(counter);
    1505           0 :   if (!otherDims) return;
    1506             :   
    1507             :   // switch to long counters if the given counter collection is of that type
    1508           0 :   if (counter->fLongCounters && !fLongCounters) {
    1509           0 :     ConvertToTHnSparseL(fCounters);
    1510           0 :     fLongCounters = kTRUE;
    1511           0 :   }
    1512             :   
    1513           0 :   Int_t nRubrics = fCounters->GetNdimensions();
    1514           0 :   Int_t* thisBins = new Int_t[nRubrics];
    1515           0 :   Int_t* otherBins = new Int_t[nRubrics];
    1516             :   
    1517             :   // loop over every filled bins inside the other counter
    1518           0 :   for (Long64_t i = 0; i < counter->fCounters->GetNbins(); i++) {
    1519             :     
    1520             :     // get the content of the bin
    1521           0 :     Double_t value = counter->fCounters->GetBinContent(i, otherBins);
    1522             :     
    1523             :     // convert "other" bin coordinates to "this" bin coordinates
    1524             :     Bool_t ok = kTRUE;
    1525           0 :     for (Int_t dim = 0; dim < nRubrics; dim++) {
    1526           0 :       TString label = counter->fCounters->GetAxis(otherDims[dim])->GetBinLabel(otherBins[otherDims[dim]]);
    1527           0 :       thisBins[dim] = FindBin(dim, label, kTRUE);
    1528           0 :       if (thisBins[dim] < 0) {
    1529           0 :         AliError("this counter is full, unable to add that key word");
    1530             :         ok = kFALSE;
    1531           0 :         break;
    1532             :       }
    1533           0 :     }
    1534           0 :     if (!ok) continue;
    1535             :     
    1536           0 :     if (fWeightedCounters || fLongCounters) {
    1537             :       
    1538             :       // increment the corresponding local counter
    1539           0 :       fCounters->AddBinContent(thisBins, value);
    1540             :       
    1541           0 :     } else {
    1542             :       
    1543             :       // switch to long counters if needed before incrementing
    1544           0 :       Long64_t linBin = fCounters->GetBin(thisBins, kTRUE);
    1545           0 :       Double_t currentValue = fCounters->GetBinContent(linBin);
    1546           0 :       if (currentValue+value > INT_MAX) {
    1547           0 :         ConvertToTHnSparseL(fCounters);
    1548           0 :         fLongCounters = kTRUE;
    1549           0 :         fCounters->AddBinContent(thisBins, value);
    1550           0 :       } else fCounters->AddBinContent(linBin, value);
    1551             :       
    1552             :     }
    1553             :     
    1554           0 :   }
    1555             :   
    1556             :   // clean memory
    1557           0 :   delete[] otherDims;
    1558           0 :   delete[] thisBins;
    1559           0 :   delete[] otherBins;
    1560           0 : }
    1561             : 
    1562             : //-----------------------------------------------------------------------
    1563             : Long64_t AliCounterCollection::Merge(TCollection* list)
    1564             : {
    1565             :   /// Merge this with a list of AliCounterCollections. All AliCounterCollections provided
    1566             :   /// must have the same rubrics with the same list of authorized key words if any.
    1567             :   
    1568           0 :   if (!list || !fCounters) return 0;
    1569           0 :   if (list->IsEmpty()) return (Long64_t)fCounters->GetEntries();
    1570             :   
    1571           0 :   TIter next(list);
    1572             :   const TObject* obj = 0x0;
    1573           0 :   while ((obj = next())) {
    1574             :     
    1575             :     // check that "obj" is an object of the class AliCounterCollection
    1576           0 :     const AliCounterCollection* counter = dynamic_cast<const AliCounterCollection*>(obj);
    1577           0 :     if (!counter) {
    1578           0 :       AliFatal(Form("object named \"%s\" is a %s instead of an AliCounterCollection!", obj->GetName(), obj->ClassName()));
    1579           0 :       continue;
    1580             :     }
    1581             :     
    1582             :     // merge counter to this one
    1583           0 :     Add(counter);
    1584             :     
    1585           0 :   }
    1586             :   
    1587           0 :   return (Long64_t)fCounters->GetEntries();
    1588           0 : }
    1589             : 
    1590             : //-----------------------------------------------------------------------
    1591             : void AliCounterCollection::Sort(Option_t* opt, Bool_t asInt)
    1592             : {
    1593             :   /// Sort rubrics defined without a list of authorized key words or all rubrics if opt=="all".
    1594             :   /// If asInt=kTRUE, key words are ordered as interger instead of alphabetically.
    1595             :   
    1596           0 :   if (!fCounters) {
    1597           0 :     AliError("counters are not initialized");
    1598           0 :     return;
    1599             :   }
    1600             :   
    1601           0 :   Bool_t all = (!strcasecmp(opt, "all"));
    1602             :   
    1603             :   Bool_t somethingToSort = kFALSE;
    1604           0 :   Int_t nRubrics = fRubrics->GetSize();
    1605           0 :   Bool_t* rubricsToSort = new Bool_t[nRubrics];
    1606           0 :   memset(rubricsToSort, kFALSE, sizeof(Bool_t) * nRubrics);
    1607             :   
    1608             :   // choose rubrics to sort
    1609             :   TObject* rubric = 0x0;
    1610           0 :   TIter nextRubric(fRubrics);
    1611           0 :   while ((rubric = nextRubric())) {
    1612             :     
    1613           0 :     if (all || dynamic_cast<TObjString*>(rubric)) {
    1614             :       
    1615             :       // check if something to sort
    1616           0 :       THashList* labels = fCounters->GetAxis((Int_t)rubric->GetUniqueID())->GetLabels();
    1617           0 :       if (!labels || labels->GetSize() < 2) continue;
    1618             :       
    1619             :       // select that rubric
    1620           0 :       rubricsToSort[(Int_t)rubric->GetUniqueID()] = kTRUE;
    1621             :       somethingToSort = kTRUE;
    1622             :       
    1623           0 :     }
    1624             :     
    1625             :   }
    1626             :   
    1627             :   // sort selected rubrics if any
    1628           0 :   if (somethingToSort) Sort(rubricsToSort, asInt);
    1629             :   
    1630             :   // clean memory
    1631           0 :   delete[] rubricsToSort;
    1632           0 : }
    1633             : 
    1634             : //-----------------------------------------------------------------------
    1635             : void AliCounterCollection::SortRubric(TString rubric, Bool_t asInt)
    1636             : {
    1637             :   /// Sort only that rubric. If asInt=kTRUE, key words are ordered as interger instead of alphabetically.
    1638             :   
    1639           0 :   if (!fCounters) {
    1640           0 :     AliError("counters are not initialized");
    1641           0 :     return;
    1642             :   }
    1643             :   
    1644           0 :   rubric.ToUpper();
    1645             :   
    1646             :   // find the rubric to sort
    1647           0 :   Int_t dim = FindDim(rubric);
    1648           0 :   if (dim < 0) return;
    1649             :   
    1650             :   // check if something to sort
    1651           0 :   THashList* labels = fCounters->GetAxis(dim)->GetLabels();
    1652           0 :   if (!labels || labels->GetSize() < 2) return;
    1653             :   
    1654             :   // select that rubric
    1655           0 :   Int_t nRubrics = fRubrics->GetSize();
    1656           0 :   Bool_t* rubricsToSort = new Bool_t[nRubrics];
    1657           0 :   memset(rubricsToSort, kFALSE, sizeof(Bool_t) * nRubrics);
    1658           0 :   rubricsToSort[dim] = kTRUE;
    1659             :   
    1660             :   // sort it
    1661           0 :   Sort(rubricsToSort, asInt);
    1662             :   
    1663             :   // clean memory
    1664           0 :   delete[] rubricsToSort;
    1665           0 : }
    1666             : 
    1667             : //-----------------------------------------------------------------------
    1668             : void AliCounterCollection::Sort(const Bool_t* rubricsToSort, Bool_t asInt)
    1669             : {
    1670             :   /// Sort labels (alphabetically or as integer) in each rubric flagged in "rubricsToSort".
    1671             :   
    1672             :   // create a new counter
    1673           0 :   THnSparse* oldCounters = fCounters;
    1674           0 :   Int_t nRubrics = fRubrics->GetSize();
    1675           0 :   if (fWeightedCounters)
    1676           0 :     fCounters = new THnSparseT<TArrayF>("hCounters", "hCounters", nRubrics, fRubricsSize->GetArray(), 0x0, 0x0);
    1677           0 :   else if (fLongCounters)
    1678           0 :     fCounters = new THnSparseT<TArrayL>("hCounters", "hCounters", nRubrics, fRubricsSize->GetArray(), 0x0, 0x0);
    1679             :   else 
    1680           0 :     fCounters = new THnSparseT<TArrayI>("hCounters", "hCounters", nRubrics, fRubricsSize->GetArray(), 0x0, 0x0);
    1681           0 :   Int_t** newBins = new Int_t*[nRubrics];
    1682             :   Bool_t newBinsFilled = kTRUE;
    1683             :   
    1684             :   // define the new axes
    1685           0 :   for (Int_t i=0; i<nRubrics; i++) {
    1686           0 :     TAxis* oldAxis = oldCounters->GetAxis(i);
    1687           0 :     TAxis* newAxis = fCounters->GetAxis(i);
    1688             :     
    1689             :     // set the name of the new axis
    1690           0 :     newAxis->SetName(oldAxis->GetName());
    1691             :     
    1692             :     // get old labels
    1693           0 :     THashList* oldLabels = oldAxis->GetLabels();
    1694           0 :     if (!oldLabels) {
    1695           0 :       newBins[i] = 0x0;
    1696             :       newBinsFilled = kFALSE;
    1697           0 :       continue;
    1698             :     }
    1699             :     
    1700             :     // sort them if required
    1701           0 :     if (rubricsToSort[i]) {
    1702           0 :       if (asInt) { oldLabels = SortAsInt(oldLabels); }
    1703           0 :       else { oldLabels->Sort(); }
    1704             :     }
    1705             :     
    1706             :     // set labels in the new axis and save the correspondence between new and old bins
    1707           0 :     newBins[i] = new Int_t[oldLabels->GetSize()+1];
    1708             :     TObjString* label = 0x0;
    1709             :     Int_t bin = 1;
    1710           0 :     TIter nextLabel(oldLabels);
    1711           0 :     while ((label = static_cast<TObjString*>(nextLabel()))) {
    1712           0 :       newAxis->SetBinLabel(bin, label->String().Data());
    1713           0 :       newBins[i][(Int_t)label->GetUniqueID()] = bin;
    1714           0 :       bin++;
    1715             :     }
    1716             :     
    1717             :     // clean memory
    1718           0 :     if (rubricsToSort[i] && asInt) delete oldLabels;
    1719           0 :   }
    1720             :   
    1721             :   // fill the new fCounters only if all axes have label(s) defined (otherwise it is empty)
    1722           0 :   if (newBinsFilled) {
    1723             :     
    1724             :     // fill the new counters
    1725           0 :     Int_t* oldCoor = new Int_t[nRubrics];
    1726           0 :     Int_t* newCoor = new Int_t[nRubrics];
    1727           0 :     for (Long64_t i = 0; i < oldCounters->GetNbins(); i++) {
    1728           0 :       Double_t value = oldCounters->GetBinContent(i, oldCoor);
    1729           0 :       for (Int_t dim = 0; dim < nRubrics; dim++) newCoor[dim] = newBins[dim][oldCoor[dim]];    
    1730           0 :       fCounters->AddBinContent(newCoor, value);
    1731             :     }
    1732             :     
    1733             :     // clean memory
    1734           0 :     delete[] oldCoor;
    1735           0 :     delete[] newCoor;
    1736           0 :   }
    1737             :   
    1738             :   // clean memory
    1739           0 :   for (Int_t i=0; i<nRubrics; i++) delete[] newBins[i];
    1740           0 :   delete[] newBins;
    1741           0 :   delete oldCounters;
    1742           0 : }
    1743             : 
    1744             : //-----------------------------------------------------------------------
    1745             : THashList* AliCounterCollection::SortAsInt(const THashList* labels)
    1746             : {
    1747             :   /// Return a list (not owner) of labels sorted assuming they are integers.
    1748             :   /// It is the responsability of user to delete the returned list.
    1749             :   
    1750           0 :   THashList* sortedLabels = new THashList(labels->GetSize());
    1751           0 :   TIter nextSortedLabel(sortedLabels);
    1752             :   
    1753             :   // loop over labels
    1754             :   TObjString* label = 0x0;
    1755           0 :   TIter nextLabel(labels);
    1756           0 :   while ((label = static_cast<TObjString*>(nextLabel()))) {
    1757             :     
    1758             :     // find where to add it
    1759             :     TObjString* sortedLabel = 0x0;
    1760           0 :     nextSortedLabel.Reset();
    1761           0 :     while ((sortedLabel = static_cast<TObjString*>(nextSortedLabel())) &&
    1762           0 :            (sortedLabel->String().Atoi() <= label->String().Atoi())) {}
    1763             :     
    1764             :     // add it
    1765           0 :     if (sortedLabel) sortedLabels->AddBefore(sortedLabel, label);
    1766           0 :     else sortedLabels->AddLast(label);
    1767             :   }
    1768             :   
    1769             :   return sortedLabels;
    1770           0 : }
    1771             : 
    1772             : //-----------------------------------------------------------------------
    1773             : void AliCounterCollection::ConvertToTHnSparseL(THnSparse* &h)
    1774             : {
    1775             :   /// Convert the given THnSparse to a THnSparseL (able to handle numbers >= 2^31)
    1776             :   
    1777             :   // create the new THnSparse
    1778           0 :   Int_t nDims = h->GetNdimensions();
    1779           0 :   Int_t* nBins = new Int_t[nDims];
    1780           0 :   for (Int_t i=0; i<nDims; i++) nBins[i] = h->GetAxis(i)->GetNbins();
    1781           0 :   THnSparse* hNew = new THnSparseT<TArrayL>("new", "new", nDims, nBins, 0x0, 0x0);
    1782           0 :   delete[] nBins;
    1783             :   
    1784             :   // transfer the axes
    1785           0 :   for (Int_t i=0; i<nDims; i++) {
    1786           0 :     TAxis* oldAxis = h->GetAxis(i);
    1787           0 :     TAxis* newAxis = hNew->GetAxis(i);
    1788             :     
    1789             :     // transfer the name
    1790           0 :     newAxis->SetName(oldAxis->GetName());
    1791             :     
    1792             :     // transfer labels
    1793             :     TObjString* label = 0x0;
    1794           0 :     TIter nextLabel(oldAxis->GetLabels());
    1795           0 :     while ((label = static_cast<TObjString*>(nextLabel())))
    1796           0 :       newAxis->SetBinLabel(label->GetUniqueID(), label->String().Data());
    1797           0 :   }
    1798             :   
    1799             :   // fill the new THnSparse
    1800           0 :   Int_t* coor = new Int_t[nDims];
    1801           0 :   for (Long64_t i = 0; i < h->GetNbins(); i++) {
    1802           0 :     Double_t value = h->GetBinContent(i, coor);
    1803           0 :     hNew->AddBinContent(coor, value);
    1804             :   }
    1805           0 :   delete[] coor;
    1806             :   
    1807             :   // transfer the number of entries
    1808           0 :   hNew->SetEntries(h->GetEntries());
    1809             :   
    1810             :   // remove old THnSparse and transfer its name and title to the new one
    1811           0 :   TString name(h->GetName());
    1812           0 :   TString title(h->GetTitle());
    1813           0 :   delete h;
    1814           0 :   h = hNew;
    1815           0 :   h->SetNameTitle(name.Data(), title.Data());
    1816           0 : }
    1817             : 

Generated by: LCOV version 1.11