AliRoot Core  3dc7879 (3dc7879)
AliQADataMaker.cxx
Go to the documentation of this file.
1 /**************************************************************************
2  * Copyright(c) 1998-1999, 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 
17 /* $Id$ */
18 
19 //
20 // Base Class
21 // Produces the data needed to calculate the quality assurance.
22 // All data must be mergeable objects.
23 // Y. Schutz CERN July 2007
24 //
25 
26 // --- ROOT system ---
27 #include <TROOT.h>
28 #include <TSystem.h>
29 #include <TFile.h>
30 #include <TList.h>
31 #include <TTree.h>
32 #include <TClonesArray.h>
33 #include <TParameter.h>
34 #include <TH1K.h>
35 #include <TH2C.h>
36 #include <TH2F.h>
37 #include <TH2F.h>
38 #include <TH2I.h>
39 #include <TH3C.h>
40 #include <TH3F.h>
41 #include <TH3F.h>
42 #include <TH3I.h>
43 #include <TH3S.h>
44 #include <TArrayI.h>
45 #include <TPRegexp.h>
46 // --- Standard library ---
47 
48 // --- AliRoot header files ---
49 #include "AliLog.h"
50 #include "AliQADataMaker.h"
51 #include "AliQAChecker.h"
52 #include "AliESDEvent.h"
53 #include "AliRawReader.h"
54 #include "AliDetectorRecoParam.h"
55 
56 
57 ClassImp(AliQADataMaker)
58 
59 const Char_t* AliQADataMaker::fgkTriggerPrefix = "_$TR$_";
60 TObjArray* AliQADataMaker::fgCloningRequest = 0;
61 TObjArray* AliQADataMaker::fgTrigClasses = 0;
62 TObjArray AliQADataMaker::fgEventTrigClasses;
63 
64 //____________________________________________________________________________
65 AliQADataMaker::AliQADataMaker(const Char_t * name, const Char_t * title) :
66  TNamed(name, title),
67  fOutput(0x0),
68  fDetectorDir(0x0),
69  fDetectorDirName(""),
70  fCurrentCycle(0),
71  fCycle(9999999),
72  fCycleCounter(0),
73  fWriteExpert(kFALSE),
74  fParameterList(new TList*[AliRecoParam::kNSpecies]),
75  fRun(0),
76  fEventSpecie(AliRecoParam::kDefault),
77  fDigitsArray(NULL)
78 {
79  // ctor
80  fDetectorDirName = GetName() ;
81  for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
82  fParameterList[specie] = NULL ;
83  fEvCountCycle[specie].Set(AliQAv1::kNTASKINDEX);
84  fEvCountTotal[specie].Set(AliQAv1::kNTASKINDEX);
85  }
86 
87 }
88 
89 //____________________________________________________________________________
91  TNamed(qadm.GetName(), qadm.GetTitle()),
92  fOutput(qadm.fOutput),
93  fDetectorDir(qadm.fDetectorDir),
94  fDetectorDirName(qadm.fDetectorDirName),
95  fCurrentCycle(qadm.fCurrentCycle),
96  fCycle(qadm.fCycle),
97  fCycleCounter(qadm.fCycleCounter),
98  fWriteExpert(qadm.fWriteExpert),
99  fParameterList(qadm.fParameterList),
100  fRun(qadm.fRun),
101  fEventSpecie(qadm.fEventSpecie),
102  fDigitsArray(NULL)
103 {
104  //copy ctor
105  fDetectorDirName = GetName() ;
106  for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
107  fParameterList[specie] = qadm.fParameterList[specie] ;
108  fEvCountCycle[specie] = qadm.fEvCountCycle[specie];
109  fEvCountTotal[specie] = qadm.fEvCountTotal[specie];
110  // fImage[specie] = qadm.fImage[specie] ;
111  }
112 }
113 
114 //____________________________________________________________________________
116 {
117  for (Int_t esIndex = 0 ; esIndex < AliRecoParam::kNSpecies ; esIndex++) {
118  if (fParameterList[esIndex] )
119  delete fParameterList[esIndex] ;
120  }
121  delete[] fParameterList ;
122  if (fDigitsArray) {
123  fDigitsArray->Clear() ;
124  delete fDigitsArray ;
125  }
126 }
127 
128 //____________________________________________________________________________
129 Int_t AliQADataMaker::Add2List(TH1 * hist, const Int_t index, TObjArray ** list, const Bool_t expert, const Bool_t image, const Bool_t saveForCorr)
130 {
131  // Set histograms memory resident and add to the list
132  // Maximm allowed is 10000
133 
134  Int_t rv = -1 ;
135  TClass * classType = hist->Class() ;
136  TString className(classType->GetName()) ;
137  if( ! className.BeginsWith("T") && ! classType->InheritsFrom("TH1") ) {
138  AliError(Form("QA data Object must be a generic ROOT object and derive fom TH1 and not %s", className.Data())) ;
139  } else if ( index > AliQAv1::GetMaxQAObj() ) {
140  AliError(Form("Max number of authorized QA objects is %d", AliQAv1::GetMaxQAObj())) ;
141  } else {
142  hist->SetDirectory(0);
143  if (expert)
144  hist->SetBit(AliQAv1::GetExpertBit()) ;
145  if (image)
146  hist->SetBit(AliQAv1::GetImageBit()) ;
147  const Char_t * name = Form("%s_%s", AliRecoParam::GetEventSpecieName(fEventSpecie), hist->GetName()) ;
148  hist->SetName(name) ;
149  if(saveForCorr) {
150  const Char_t * cname = Form("%s_%s", list[AliRecoParam::AConvert(AliRecoParam::kDefault)]->GetName(), hist->GetName()) ;
151  TParameter<double> * p = new TParameter<double>(cname, 9999.9999) ;
153  {
155  // fParameterList[AliRecoParam::AConvert(fEventSpecie)]->SetOwner(kTRUE);
156  }
158  }
159  TObject* old = list[AliRecoParam::AConvert(fEventSpecie)]->At(index);
160  if (old) {
161  AliError(Form("%s - OUPS ! Already got an object (%p,%s) for index=%d => will most probably get a memory leak by replacing it with (%p,%s) !",
162  GetName(),old,old->GetName(),index,hist,hist->GetName()));
163  }
164  list[AliRecoParam::AConvert(fEventSpecie)]->AddAtAndExpand(hist, index) ;
165  rv = list[AliRecoParam::AConvert(fEventSpecie)]->GetLast() ;
166  }
167  return rv ;
168 }
169 
170 //____________________________________________________________________________
172 {
173  // scan the histos of the list, match them to requested histo names to be
174  // cloned and create the clones per trigger class
176  if (!fgCloningRequest || !GetNTrigClasses()) return;
177  if (!list || !list[spec]) {
178  AliDebug(1,Form("Array for %s specie is not created",AliRecoParam::GetEventSpecieName(fEventSpecie)));
179  return;
180  }
181  //
182  // if the counters were not expanded, do this now
183  if (fEvCountCycle[spec].GetSize()==AliQAv1::kNTASKINDEX) {
184  fEvCountCycle[spec].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
185  fEvCountTotal[spec].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
186  }
187  //
188 
189  TString prefix = Form("%s/%s/",GetName(),AliQAv1::GetTaskName(task).Data()); // take care of requests with this prefix
190  int prefLgt = prefix.Length();
191  //
192  for (int ir=fgCloningRequest->GetEntriesFast();ir--;) {
193  TNamed* rec = dynamic_cast<TNamed*>(fgCloningRequest->At(ir));
194  if (!rec) continue;
195  TString hfname = rec->GetName(); // histogram names
196  if (!hfname.BeginsWith(prefix)) continue;
197  Bool_t keepOrig = rec->TestBit(AliQAv1::GetOrigHistoKeptBit()); // is original to be kept?
198  ClonePerTrigClassA(list[spec], hfname.Data()+prefLgt, rec->GetTitle(), keepOrig);
199  }
200  //
201 }
202 
203 //____________________________________________________________________________
204 Int_t AliQADataMaker::ClonePerTrigClassA(TObjArray * list, const char* hnm, const char* triggers, Bool_t keepOriginal)
205 {
206  // substitute the matching histogram by the TObjArray containing clones of
207  // original histogram for each trigger from the space-separated tiggers string
208  // When keepOriginal is requested, the original histo is not deleted and filled for each trigger
209  if (!list) return 0;
210  int nh = list->GetEntriesFast();
211  if (!nh) return 0;
212  //
213  AliDebug(AliQAv1::GetQADebugLevel(),Form("Cloning histogram %s for triggers %s in array %s",hnm,triggers,list->GetName()));
214  //
215  TString trigStr = triggers;
216  TObjArray* trigArr = trigStr.Tokenize(" ");
217  int nTrigs = trigArr->GetEntriesFast();
218  Bool_t cloneAll=kFALSE, cloneMany=kFALSE;
219  if (!nTrigs) {
220  AliError(Form("Triggers string supplied for histo %s is empty", hnm));
221  delete trigArr;
222  return 0;
223  }
224  // match the trigger class id to selected aliases
225  for (int i=nTrigs;i--;) {
226  TObject* alias = fgTrigClasses->FindObject( trigArr->At(i)->GetName() );
227  if (!alias) {
228  AliError(Form("Cloning for undefined trigger class %s was requested for histogram %s",trigArr->At(i)->GetName(),hnm));
229  delete trigArr->RemoveAt(i);
230  trigArr->Compress();
231  continue;
232  }
233  trigArr->At(i)->SetUniqueID( alias->GetUniqueID() );
234  }
235  //
236  TString histPatt = hnm;
237  if (histPatt == "*") {
238  cloneAll = kTRUE;
239  cloneMany = kTRUE;
240  }
241  else {
242  histPatt.Prepend(Form("%s_", AliRecoParam::GetEventSpecieName(fEventSpecie)));
243  //
244  // The histogram name may contain %d formats for histos created in loop.
245  // Then we expect more than 1 histo matching to name
246  TPRegexp rgx("%\\d*d");
247  if (histPatt.Contains(rgx)) { // need to convert to perl expression, make sure there are no perl special characters
248  const char *specials = "^$.{}[]*+?\\";
249  for (int i=strlen(specials);i--;) histPatt.ReplaceAll(specials+i,1,Form("\\%c",specials[i]),2);
250  rgx.Substitute(histPatt,"\\d+","g");
251  histPatt.Prepend('^'); histPatt += "$";
252  cloneMany = kTRUE;
253  }
254  else if ( histPatt.Contains("*") ) {
255  histPatt.ReplaceAll("*",".*");
256  histPatt.Prepend('^'); histPatt += "$";
257  cloneMany = kTRUE;
258  }
259  }
260  //
261  int nCloned = 0;
262  for (int ih=0;ih<nh;ih++) {
263  TH1* hist = (TH1*)list->At(ih);
264  if (!hist) continue;
265  if (!cloneAll) {
266  TString hname = hist->GetName();
267  if (cloneMany) {
268  TPRegexp patPR(histPatt);
269  if ( !hname.Contains(patPR) ) continue;
270  }
271  else {
272  if ( hname.CompareTo(histPatt) ) continue;
273  }
274  }
275  //
276  // histo name matches, clone it
277  nCloned += ClonePerTrigClassH(ih, list, trigArr, keepOriginal);
278  if (!cloneMany) break; // no wildcards, just one histo is expected
279  }
280  //
281  delete trigArr;
282  return nCloned;
283 }
284 
285 //____________________________________________________________________________
286 Int_t AliQADataMaker::ClonePerTrigClassH(Int_t index, TObjArray* list, TObjArray* trigArr, Bool_t keepOriginal)
287 {
288  // substitute the histogram at position index by the TObjArray containing clones of
289  // original histogram for each trigger from the trigArr
290  // When keepOriginal is requested, the original histo is not deleted and filled for each trigger
291  TH1* hist = (TH1*) list->At(index);
292  if (!hist) return 0; // should never happen, checked in calling method
293 
294  if (IsCloningForbidden(hist)) {
295  AliError(Form("Cloning per trigger is forbidden for histo %s at slot %d",hist->GetName(),index));
296  return 0;
297  }
298  //
299  if (hist->TestBit(AliQAv1::GetClonedBit())) {
300  AliError(Form("histo %s at slot %d was already cloned!",((TObjArray*)hist)->GetName(),index));
301  return 0;
302  }
303  //
304  int nTrigs = trigArr->GetEntriesFast();
305  TObjArray* clonesArr = new TObjArray(GetNTrigClasses()+keepOriginal);
306  // transfer the user bits of the histo to be cloned to array
307  for (int ib=14;ib<=23;ib++) if (hist->TestBit(1<<ib)) clonesArr->SetBit(1<<ib);
308  //
309  if (keepOriginal) {
310  clonesArr->AddAt(hist,GetNTrigClasses());
311  clonesArr->SetBit(AliQAv1::GetOrigHistoKeptBit());
312  }
313  clonesArr->SetBit(AliQAv1::GetClonedBit());
314  clonesArr->SetName(hist->GetName());
315  for (int itr=0;itr<nTrigs;itr++) {
316  TObject* trigClass = trigArr->At(itr);
317  TH1* hclone = (TH1*)hist->Clone(Form("%s%s%s",hist->GetName(), fgkTriggerPrefix, trigClass->GetName()));
318  hclone->SetTitle(Form("%s %s",hist->GetTitle(), trigClass->GetName()));
319  hclone->SetDirectory(hist->GetDirectory());
320  //
321  // NOTE: the clone is added at position corresponding to ID of the trigger alias
322  clonesArr->AddAt(hclone, trigClass->GetUniqueID());
323  hclone->SetBit(AliQAv1::GetClonedBit());
324  AliDebug(AliQAv1::GetQADebugLevel(),Form("Cloned histogram %s for trigger class %s",hist->GetName(),trigClass->GetName()));
325  }
326  //
327  list->RemoveAt(index); // remove original histogram
328  list->AddAt(clonesArr, index);
329  if (!keepOriginal) delete hist;
330  //
331  clonesArr->SetOwner(kTRUE);
332  return clonesArr->GetEntries();
333 }
334 
335 //____________________________________________________________________________
336 Char_t* AliQADataMaker::GetHistoTrigger(const TH1* h) const
337 {
338  // extract the name of the trigger from the histogram name
339  if (!h || !h->TestBit(AliQAv1::GetClonedBit())) return 0;
340  TString hnm = h->GetName();
341  int idx = hnm.Index(fgkTriggerPrefix);
342  if (idx<0) return 0; // not cloned
343  return (char*) h->GetName() + idx + sizeof(fgkTriggerPrefix) - 1;
344 }
345 
346 //____________________________________________________________________________
347 Int_t AliQADataMaker::SetEventTrigClasses(const char* triggers)
348 {
349  // sets the array of triggers fired in given event, return the number of triggers
350  //
352  fgEventTrigClasses.SetUniqueID(1); // flag that this is a triggered event
353  if (!GetNTrigClasses()) return 0; // meaningless if the trigger aliases are not set
354  TString trigStr = triggers;
355  TObjArray* tarr = trigStr.Tokenize(" ");
356  int nTrigs = tarr->GetEntriesFast();
357  if (!nTrigs) {
358  AliWarningClass("The string for event triggers is empty");
359  delete tarr;
360  return 0;
361  }
362  int nTrClasses = 0;
363  for (int ial=fgTrigClasses->GetEntriesFast();ial--;) {
364  TNamed *pair = (TNamed*)fgTrigClasses->At(ial);
365  TString triggSet = pair->GetTitle(); // list of trigger names
366  for (int itr=nTrigs;itr--;) {
367  if ( !triggSet.Contains(tarr->At(itr)->GetName()) ) continue;
368  fgEventTrigClasses.Add(pair);
369  nTrClasses++;
370  break;
371  }
372  }
373  //
374  fgEventTrigClasses.SetOwner(kFALSE);
375  delete tarr;
376  //
377  return nTrClasses;
378 }
379 
380 //____________________________________________________________________________
381 TH1* AliQADataMaker::GetMatchingHisto(TObjArray ** list, Int_t index, Int_t trigId)
382 {
383  // get histo with given index matching to trigId-th current trigger class
384  // trigId < 0 means default hist (only if cloning was done)
385  TObject* data = GetData(list,index);
386  if (!data) return 0;
387  if (trigId<0 || trigId==GetNEventTrigClasses()) { // original histo is requested
388  if (!data->TestBit(AliQAv1::GetClonedBit())) return (TH1*)data; // was not cloned per trigger
389  // check if during the cloning the original histo was kept (always at slot GetNTrigClasses())
390  else if (data->TestBit(AliQAv1::GetOrigHistoKeptBit())) return (TH1*)((TObjArray*)data)->At(GetNTrigClasses());
391  return 0;
392  }
393  //
394  if (!data->TestBit(AliQAv1::GetClonedBit())) return 0; // no cloning was done
395  if (trigId>GetNEventTrigClasses()) {
396  AliError(Form("Current event has %d triggers only, %d-th is requested",GetNEventTrigClasses(),trigId));
397  return 0; // invalid trigger
398  }
399  int slot = fgEventTrigClasses.At(trigId)->GetUniqueID(); // the histos are at slots corresponding to trig.class ID
400  return (TH1*)((TObjArray*)data)->At(slot);
401  //
402 }
403 
404 //____________________________________________________________________________
405 TObjArray* AliQADataMaker::GetMatchingHistosSet(TObjArray ** list, const Int_t* indexList, Int_t nHist, Int_t trigId)
406 {
407  // get set of nHist histos with indices from the indexList matching to trigId-th current trigger
408  // Note: a static array is returned, it will be overwritten at the next call
409  static TObjArray garr;
410  garr.Clear();
411  for (int ih=0;ih<nHist;ih++) {
412  TH1* histo = GetMatchingHisto(list, indexList[ih],trigId);
413  if (!histo) return 0; // if at least 1 histo is not found, return nothing
414  garr.Add(histo);
415  }
416  return &garr;
417 }
418 
419 //____________________________________________________________________________
420 Bool_t AliQADataMaker::CheckCloningConsistency(TObjArray ** list, const Int_t* indexList, Int_t nHist, Bool_t checkTriggers)
421 {
422  // Make sure that histograms at slots mentioned in the indexList are either
423  // not cloned per trigger or
424  // cloned for the same amount of triggers and if original histo was kept, then it is done for all histos.
425  // If checkTriggers is requested, apart from clones count also the trigger names are checked
426  //
427  // This consistency check is needed to ensure validity of the operations over the group of histograms in the EndOfDetectorCycle's
428  //
429  TObjArray* refArr = 0;
430  int refSlot = -1;
431  for (int isl=0;isl<nHist;isl++) {
432  int slot = indexList[isl];
433  TObject* data = GetData(list,slot);
434  if (!data) {AliError(Form("Slot %d is not booked",slot)); return kFALSE;}
435  //
436  if (refSlot<0) { // just take the 1st mentioned slot as a reference;
437  if (data->TestBit(AliQAv1::GetClonedBit())) refArr = (TObjArray*) data; // data was cloned
438  refSlot = slot;
439  continue;
440  }
441  //
442  if (!data->TestBit(AliQAv1::GetClonedBit())) { // this slot is not cloned, compare with reference
443  if (refArr) {AliError(Form("Slot %d is not cloned, slot %d is cloned",slot, refSlot)); return kFALSE;}
444  else continue;
445  }
446  //
447  TObjArray* currArr = (TObjArray*) data; // current slot is cloned
448  if (!refArr) {AliError(Form("Slot %d is not cloned, slot %d is cloned",refSlot,slot)); return kFALSE;}
449  //
450  // both are cloned
451  if (refArr->GetEntriesFast()!=currArr->GetEntriesFast()) {
452  AliError(Form("Different number of clones: slot %d: %d vs slot %d: %d",
453  refSlot,refArr->GetEntriesFast(), slot,currArr->GetEntriesFast()));
454  return kFALSE;
455  }
456  //
457  if (refArr->TestBit(AliQAv1::GetOrigHistoKeptBit())!=currArr->TestBit(AliQAv1::GetOrigHistoKeptBit())) {
458  AliError(Form("Slot %d kept original histo, slot %d did not",
459  refArr->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? refSlot:slot,refArr->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? slot:refSlot));
460  return kFALSE;
461  }
462  //
463  if (checkTriggers) {
464  for (int ih=refArr->GetEntriesFast();ih--;) {
465  TH1* hRef = (TH1*)refArr->At(ih);
466  if (!hRef->TestBit(AliQAv1::GetClonedBit())) continue; // original histo was kept, no trigger name is expected
467  TString hnm = ((TH1*)currArr->At(ih))->GetName();
468  if (!hnm.EndsWith( GetHistoTrigger(hRef) )) {
469  AliError(Form("Slots %d and %d have different trigger names for clone %d: %s vs %s",
470  refSlot,slot,ih,hRef->GetName(),hnm.Data()));
471  return kFALSE;
472  }
473  }
474  }
475  }
476  //
477  return kTRUE;
478 }
479 
480 //____________________________________________________________________________
482 {
483  // return all histograms of given index matching to any trigger in the current event trigger's list
484  // If the destination optDest is provided - use it, otherwise fill/return own static array
485  // In the latter case one should be careful: the content is overwritten at each call
486  // If the original histo was cloned but kept, it is also returned
487  //
488  // Note: if there are no triggers set, all eventual clones are returned
489  // (used for EndOfDetectorCycle loop over all histos)
490  static TObjArray garr;
491  TObjArray *dest = optDest ? optDest : &garr;
492  dest->SetOwner(kFALSE);
493  dest->Clear();
494  TObject* data = GetData(list,index);
495  if (!data) return 0;
496  if (!data->TestBit(AliQAv1::GetClonedBit())) dest->AddLast(data); // not cloned per trigger
497  else {
498  TObjArray* arr = dynamic_cast<TObjArray*>(data);
499  if (!arr) return 0;
500  if (IsEventTriggerSet()) {
501  int ncl = GetNEventTrigClasses();
502  for (int icl=0;icl<ncl;icl++) {
503  int indCl = GetEventTrigClass(icl)->GetUniqueID();
504  // AliInfo(Form("Ind %d at %d of %p of %p",index,indCl, arr, list[AliRecoParam::AConvert(fEventSpecie)]));
505  TH1* histo = dynamic_cast<TH1*>(arr->At(indCl));
506  if (histo) dest->AddLast(histo);
507  // AliInfo(Form("EvCl%d IndTr%d add to %d IndH %d %p %s",icl,indCl,dest->LastIndex(),index,histo,histo ? histo->GetName():"XXX"));
508  }
509  // check if original histo was kept
510  if (arr->TestBit(AliQAv1::GetOrigHistoKeptBit())) {
511  TH1* histo = dynamic_cast<TH1*>(arr->At(GetNTrigClasses()));
512  if (histo) dest->AddLast(histo);
513  // AliInfo(Form("Def add to %d inex: %d %p %s",dest->LastIndex(),index,histo,histo ? histo->GetName():"XXX"));
514  }
515  }
516  else { // trigger is not set, return all clones
517  for (int ih=arr->GetEntriesFast();ih--;) if (arr->At(ih)) dest->AddLast(arr->At(ih));
518  }
519  }
520  return dest;
521 }
522 
523 //____________________________________________________________________________
524 Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x)
525 {
526  // fills single histo or its trigger-dependent clones, return number of histos filled
527  TObjArray* arr = GetMatchingHistos(list,index);
528  int count = 0;
529  if (arr) {
530  count = arr->GetEntriesFast();
531  for (int ih=count;ih--;){
532  TH1 *histo = (TH1*)arr->UncheckedAt(ih);
533  if (histo) histo->Fill(x);
534  }
535  }
536  return count;
537 }
538 
539 //____________________________________________________________________________
540 Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x, double y)
541 {
542  // fills single histo or its trigger-dependent clones, return number of histos filled
543  TObjArray* arr = GetMatchingHistos(list,index);
544  int count = 0;
545  if (arr) {
546  count = arr->GetEntriesFast();
547  for (int ih=count;ih--;){
548  TH1 *histo=(TH1*)arr->UncheckedAt(ih);
549  if (histo) histo->Fill(x,y);
550  }
551  }
552  return count;
553 }
554 
555 //____________________________________________________________________________
556 Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x, double y, double z)
557 {
558  // fills single histo or its trigger-dependent clones, return number of histos filled
559  TObjArray* arr = GetMatchingHistos(list,index);
560  int count = 0;
561  if (arr) {
562  count = arr->GetEntriesFast();
563  for (int ih=count;ih--;) if ((TH2*)arr->At(ih)) ((TH2*)arr->At(ih))->Fill(x,y,z);
564  }
565  return count;
566 }
567 
568 //____________________________________________________________________________
569 Int_t AliQADataMaker::SetDataBinContent(TObjArray ** list, Int_t index, int bin, double w)
570 {
571  // set bin content of single histo or its trigger-dependent clones, return number of histos filled
572  TObjArray* arr = GetMatchingHistos(list,index);
573  int count = 0;
574  if (arr) {
575  count = arr->GetEntriesFast();
576  for (int ih=count;ih--;) if ((TH2*)arr->At(ih)) ((TH2*)arr->At(ih))->SetBinContent(bin,w);
577  }
578  return count;
579 }
580 
581 //____________________________________________________________________________
582 Int_t AliQADataMaker::SetDataBinContent(TObjArray ** list, Int_t index, int binX, int binY, double w)
583 {
584  // set bin content of single histo or its trigger-dependent clones, return number of histos filled
585  TObjArray* arr = GetMatchingHistos(list,index);
586  int count = 0;
587  if (arr) {
588  count = arr->GetEntriesFast();
589  for (int ih=count;ih--;) if ((TH2*)arr->At(ih)) ((TH2*)arr->At(ih))->SetBinContent(binX,binY,w);
590  }
591  return count;
592 }
593 
594 //____________________________________________________________________________
595 Int_t AliQADataMaker::SetDataBinError(TObjArray ** list, Int_t index, int bin, double err)
596 {
597  // set bin content of single histo or its trigger-dependent clones, return number of histos filled
598  TObjArray* arr = GetMatchingHistos(list,index);
599  int count = 0;
600  if (arr) {
601  count = arr->GetEntriesFast();
602  for (int ih=count;ih--;) if ((TH2*)arr->At(ih)) ((TH2*)arr->At(ih))->SetBinError(bin,err);
603  }
604  return count;
605 }
606 
607 //____________________________________________________________________________
608 Int_t AliQADataMaker::SetDataBinError(TObjArray ** list, Int_t index, int binX, int binY, double err)
609 {
610  // set bin content of single histo or its trigger-dependent clones, return number of histos filled
611  TObjArray* arr = GetMatchingHistos(list,index);
612  int count = 0;
613  if (arr) {
614  count = arr->GetEntriesFast();
615  for (int ih=count;ih--;) if ((TH2*)arr->At(ih)) ((TH2*)arr->At(ih))->SetBinError(binX,binY,err);
616  }
617  return count;
618 }
619 
620 //____________________________________________________________________________
621 Int_t AliQADataMaker::ResetData(TObjArray ** list, Int_t index, Option_t* option)
622 {
623  // reset content of single histo or its trigger-dependent clones, return number of histos processed
624  TObjArray* arr = GetMatchingHistos(list,index);
625  int count = 0;
626  if (arr) {
627  count = arr->GetEntriesFast();
628  for (int ih=count;ih--;) if ((TH1*)arr->At(ih)) ((TH1*)arr->At(ih))->Reset(option);
629  }
630  return count;
631 }
632 
633 //____________________________________________________________________________
634 Int_t AliQADataMaker::ResetStatsData(TObjArray ** list, Int_t index)
635 {
636  // reset stats of single histo or its trigger-dependent clones, return number of histos processed
637  TObjArray* arr = GetMatchingHistos(list,index);
638  int count = 0;
639  if (arr) {
640  count = arr->GetEntriesFast();
641  for (int ih=count;ih--;) if ((TH1*)arr->At(ih)) ((TH1*)arr->At(ih))->ResetStats();
642  }
643  return count;
644 }
645 
646 //____________________________________________________________________________
647 TH1 * AliQADataMaker::CloneMe(TH1 * hist, Int_t specie) const
648 {
649  // clones a histogram
650  const Char_t * name = Form("%s_%s", AliRecoParam::GetEventSpecieName(specie), hist->GetName()) ;
651  TH1 * hClone = static_cast<TH1 *>(hist->Clone(name)) ;
652  if ( hist->TestBit(AliQAv1::GetExpertBit()) )
653  hClone->SetBit(AliQAv1::GetExpertBit()) ;
654  if ( hist->TestBit(AliQAv1::GetImageBit()) )
655  hClone->SetBit(AliQAv1::GetImageBit()) ;
656  return hClone ;
657 }
658 
659 //____________________________________________________________________________
661 {
662  // this method must be oveloaded by detectors
663  // sets the QA result to Fatal
665  AliQAv1 * qa = AliQAv1::Instance(task) ;
666  for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
667  qa->Set(AliQAv1::kFATAL, specie) ;
668  AliQAv1::GetQAResultFile()->cd() ;
669  qa->Write(AliQAv1::GetQAName(), kWriteDelete) ;
670  AliQAv1::GetQAResultFile()->Close() ;
671 }
672 
673 //____________________________________________________________________________
675 {
676  // write to the output File
677  if (fOutput)
678  fOutput->Close() ;
679 }
680 
681 //____________________________________________________________________________
682 TH1* AliQADataMaker::GetData(TObjArray ** list, const Int_t index, int cloneID)
683 {
684  // get the cloneID-th clone of the histo, -1 for original (if kept)
685  TObject* data = GetData(list,index);
686  if (!data) return 0;
687  Bool_t orig = cloneID<0 || cloneID==GetNTrigClasses();
688  if (data->TestBit(AliQAv1::GetClonedBit())) {
689  if (orig) return data->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? (TH1*)((TObjArray*)data)->UncheckedAt(GetNTrigClasses()) : 0;
690  else return (TH1*)((TObjArray*)data)->UncheckedAt(cloneID); // there was a cloning
691  }
692  //
693  // not cloned, is the original histo requested?
694  if (cloneID<0 || cloneID==GetNTrigClasses()) return (TH1*)data;
695  return 0;
696  //
697 }
698 
699 //____________________________________________________________________________
700 TObjArray* AliQADataMaker::GetDataOfTrigClass(TObjArray ** list, Int_t specieIndex, int cloneID, TObjArray *dest)
701 {
702  // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
703  // a single array (if dest is not provided, use its own static array).
704  // Existing histos are attached at their original positions
705  if (!list) return 0x0;
706  TObjArray* arr = list[specieIndex] ;
707  return GetDataOfTrigClass(arr, cloneID, dest);
708 }
709 
710 //____________________________________________________________________________
712 {
713  // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
714  // a single array (if dest is not provided, use its own static array).
715  // Existing histos are attached at their original positions
716  static TObjArray arrTransf;
717  TObjArray* destS = dest ? dest : &arrTransf;
718  destS->SetOwner(kFALSE);
719  destS->Clear();
720  if (arr) {
721  Bool_t orig = cloneID<0 || cloneID==GetNTrigClasses(); // is trigger-blind histo requested?
722  int nh = arr->GetEntriesFast();
723  if (nh>destS->GetSize()) destS->Expand(nh);
724  for (int ih=nh;ih--;) {
725  TObject* ob = arr->At(ih);
726  if (!ob) continue;
727  //
728  if (ob->TestBit(AliQAv1::GetClonedBit())) { // this is array of cloned histos
729  if (orig) ob = ob->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? ((TObjArray*)ob)->At(GetNTrigClasses()) : 0;
730  else ob = ((TObjArray*)ob)->At(cloneID);
731  }
732  else if (!orig) ob = 0; // histogram was not cloned but the clone is requested
733  if (!ob) continue;
734  (*destS)[ih] = ob;
735  }
736  destS->SetUniqueID(arr->GetUniqueID());
737  }
738  return destS;
739  //
740 }
741 
742 //____________________________________________________________________________
744 {
745  // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
746  // a single array (if dest is not provided, use its own static array).
747  // Existing histos are attached at their original positions
748  //
749  GetData(list,0); //just to initialize, if needed
750  Int_t esindex = AliRecoParam::AConvert(fEventSpecie);
751  return GetDataOfTrigClass(list, esindex, cloneID, dest);
752  //
753 }
754 
755 //____________________________________________________________________________
756 TObject * AliQADataMaker::GetData(TObjArray ** list, const Int_t index)
757 {
758  // Returns the QA object at index. Limit is AliQAv1::GetMaxQAObj()
759  if ( ! list ) {
760  AliError("Data list is NULL !!") ;
761  return NULL ;
762  }
763  Int_t esindex = AliRecoParam::AConvert(fEventSpecie) ;
764  TObject* histClone = NULL ;
765  TObjArray * arr = list[esindex] ;
766  if (arr) {
767  if ( ! arr->GetEntriesFast() ) {
768  // Initializes the histograms
769  TString arrName(arr->GetName()) ;
770  if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kRAWS)))
771  InitRaws() ;
772  else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kHITS)))
773  InitHits() ;
774  else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kSDIGITS)))
775  InitSDigits() ;
776  else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kDIGITS)))
777  InitDigits() ;
778  else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kDIGITSR)))
779  InitDigits() ;
780  else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kRECPOINTS)))
781  InitRecPoints() ;
782  else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kESDS)))
783  InitESDs() ;
784  }
785  if ( index > AliQAv1::GetMaxQAObj() ) {
786  AliError(Form("Max number of authorized QA objects is %d", AliQAv1::GetMaxQAObj())) ;
787  } else {
788  if ( arr->At(index) ) {
789  histClone = arr->At(index);
790  }
791  }
792  }
793  return histClone ;
794 }
795 
796 //____________________________________________________________________________
798 {
799  // Initialializes and returns the QAData list for a given event specie
800  TObjArray ** ar = Init(task, cycles) ;
801  return ar[AliRecoParam::AConvert(es)] ;
802 }
803 
804 //____________________________________________________________________________
805 Bool_t AliQADataMaker::IsValidEventSpecie(Int_t eventSpecieIndex, TObjArray ** list)
806 {
807  // check if event specie was present in current run or
808  // if histograms of this event specie have been created
809  if (! AliQAv1::Instance(AliQAv1::GetDetIndex(GetName()))->IsEventSpecieSet(AliRecoParam::ConvertIndex(eventSpecieIndex)) || ! list[eventSpecieIndex]->GetEntriesFast() )
810  return kFALSE ;
811  else
812  return kTRUE ;
813 }
814 
815 //____________________________________________________________________________
817 {
818  // set associations {trigger names} <-> {trigger class alias}
819  //
820  const UInt_t kDummyID = 0xffff;
821  //
823  AliWarningClass("Cloning request is already set");
824  return;
825  }
827  if (!aliases || !histos) {
828  AliWarningClass("Cloning request is incomplete");
829  return;
830  }
831  fgTrigClasses = aliases;
832  fgCloningRequest = histos;
833  //
834  // flag those aliases which are actually used
835  fgCloningRequest->Compress();
836  fgTrigClasses->Compress();
837  int nalias = fgTrigClasses->GetEntriesFast();
838  int nhisto = fgCloningRequest->GetEntriesFast();
839  //
840  int naliasUsed = 0;
841  for (int ial=0;ial<nalias;ial++) fgTrigClasses->At(ial)->SetUniqueID(kDummyID); // reset usage flag
842  //
843  for (int ih=nhisto;ih--;) {
844  TNamed* histo = (TNamed*)fgCloningRequest->At(ih);
845  TString histoReq = histo->GetTitle(); // list of aliases for which the histo must be cloned
846  TObjArray* alList = histoReq.Tokenize(" ");
847  //
848  if (!alList) {
849  AliErrorClass(Form("Invalid cloning request is found for histo %s :|%s|",histo->GetName(),histo->GetTitle()));
850  fgCloningRequest->RemoveAt(ih);
851  delete histo;
852  continue;
853  }
854  TString confirmedAliases = "";
855  for (int iha=alList->GetEntriesFast();iha--;) {
856  // check if corresponding alias is defined
857  Bool_t aliasOK = kFALSE;
858  for (int ial=0;ial<nalias;ial++) {
859  TNamed* alias = (TNamed*)fgTrigClasses->At(ial);
860  TString aliasName = alias->GetName();
861  if (aliasName == alList->At(iha)->GetName()) { // found
862  aliasOK = kTRUE;
863  if (alias->GetUniqueID() == kDummyID) alias->SetUniqueID(naliasUsed++); // acknowledge used alias
864  }
865  }
866  if (!aliasOK) {
867  AliErrorClass(Form("Cloning for undefined trigger alias %s is requested for histo %s, SUPPRESSING",
868  alList->At(iha)->GetName(),histo->GetName()));
869  }
870  else confirmedAliases += Form("%s ",alList->At(iha)->GetName());
871  }
872  if (confirmedAliases.IsNull()) {
873  AliErrorClass(Form("All requested trigger aliases for histo %s are undefined, SUPPRESSING",histo->GetName()));
874  fgCloningRequest->RemoveAt(ih);
875  delete histo;
876  }
877  else histo->SetTitle(confirmedAliases.Data());
878  //
879  delete alList;
880  }
881  fgCloningRequest->Compress();
882  //
883  // check if there are unused aliases
884  naliasUsed = 0;
885  for (int ial=0;ial<nalias;ial++) {
886  TNamed* alias = (TNamed*)fgTrigClasses->At(ial);
887  if (alias->GetUniqueID() != kDummyID) alias->SetUniqueID(naliasUsed++); // count as defined
888  else {
889  AliWarningClass(Form("Suppressing unused trigger alias %s\t->\t%s",alias->GetName(),alias->GetTitle()));
890  delete fgTrigClasses->RemoveAt(ial);
891  }
892  }
893  fgTrigClasses->Compress();
894  //
895  AliInfoClass("Confirmed aliases for trigger classes:");
896  for (int i=0;i<fgTrigClasses->GetEntriesFast();i++) {
897  TNamed* item = (TNamed*)fgTrigClasses->At(i);
898  AliInfoClass(Form("%s -> %s",item->GetName(),item->GetTitle()));
899  }
900  //
901  AliInfoClass("Confirmed histograms to clone:");
902  for (int i=0;i<fgCloningRequest->GetEntriesFast();i++) {
903  TNamed* item = (TNamed*)fgCloningRequest->At(i);
904  AliInfoClass(Form("%s -> %s %s",item->GetName(),item->GetTitle(),
905  item->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? " + TriggerBlind":""));
906  }
907  //
908 }
909 
910 //____________________________________________________________________________
912 {
913  // incerment by "diff" the cycle counters for the current event trigger classes (+ the global one)
914  int ncl = GetNTrigClasses();
916  //
917  if (fEvCountCycle[isp].GetSize()==AliQAv1::kNTASKINDEX && ncl>0) fEvCountCycle[isp].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
918  //
919  fEvCountCycle[isp][task*(1+ncl)+ncl] += diff; // trigger independent counter
920  for (int icl=GetNEventTrigClasses();icl--;) fEvCountCycle[isp][task*(1+ncl)+ GetEventTrigClass(icl)->GetUniqueID()] += diff;
921 }
922 
923 //____________________________________________________________________________
925 {
926  // incerment by "diff" the cycle counters for the current event trigger classes (+ the global one)
927  int ncl = GetNTrigClasses();
929  //
930  if (fEvCountTotal[isp].GetSize()==AliQAv1::kNTASKINDEX && ncl>0) fEvCountTotal[isp].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
931  //
932  fEvCountTotal[isp][task*(1+ncl)+ncl] += diff; // trigger independent counter
933  for (int icl=GetNEventTrigClasses();icl--;) fEvCountTotal[isp][task*(1+ncl)+ GetEventTrigClass(icl)->GetUniqueID()] += diff;
934 }
935 
936 //____________________________________________________________________________
938 {
939  // reset counter for specific trigger class for specific specie (within the cycle)
940  int ncl = GetNTrigClasses();
941  // check if it was already expanded
942  if (fEvCountCycle[isp].GetSize()==AliQAv1::kNTASKINDEX) fEvCountCycle[isp].Set(AliQAv1::kNTASKINDEX*(ncl+1));
943  for (int icl=ncl+1;icl--;) fEvCountCycle[AliRecoParam::AConvert(isp)][task*(1+ncl) + icl] = 0;
944 }
945 
946 //____________________________________________________________________________
948 {
949  // reset counter for specific trigger class for specific specie (global count)
950  int ncl = GetNTrigClasses();
951  // check if it was already expanded
952  if (fEvCountTotal[isp].GetSize()==AliQAv1::kNTASKINDEX) fEvCountTotal[isp].Set(AliQAv1::kNTASKINDEX*(ncl+1));
953  for (int icl=ncl+1;icl--;) fEvCountTotal[AliRecoParam::AConvert(isp)][task*(1+ncl) + icl] = 0;
954 }
955 
956 //____________________________________________________________________________
958 {
959  // get counter for specific trigger class for specific specie (within the cycle)
960  int ncl = GetNTrigClasses();
961  return fEvCountCycle[AliRecoParam::AConvert(isp)][task*(1+ncl) + (trCl<0||trCl>=ncl ? ncl:trCl)];
962 }
963 //____________________________________________________________________________
965 {
966  // get counter for specific trigger class for specific specie (global count)
967  int ncl = GetNTrigClasses();
968  return fEvCountTotal[AliRecoParam::AConvert(isp)][task*(1+ncl) + (trCl<0||trCl>=ncl ? ncl:trCl)];
969 }
970 
static UShort_t GetMaxQAObj()
Definition: AliQAv1.h:75
static const char * GetEventSpecieName(EventSpecie_t es)
static UInt_t GetImageBit()
Definition: AliQAv1.h:55
Bool_t CheckCloningConsistency(TObjArray **list, const Int_t *indexList, Int_t nHist, Bool_t checkTriggers=kFALSE)
TH1 * CloneMe(TH1 *hist, Int_t specie) const
static const Char_t * fgkTriggerPrefix
TList ** fParameterList
flag to write or not the expert QA data
static UInt_t GetExpertBit()
Definition: AliQAv1.h:54
virtual Int_t ClonePerTrigClassA(TObjArray *list, const char *hnm, const char *triggers, Bool_t keepOriginal=kFALSE)
void Finish() const
static TObjArray * fgTrigClasses
static UInt_t GetOrigHistoKeptBit()
Definition: AliQAv1.h:87
void IncEvCountCycle(AliQAv1::TASKINDEX_t task, Int_t diff=1)
#define TObjArray
static void SetCloningRequest(TObjArray *aliases, TObjArray *histos)
virtual Int_t ClonePerTrigClassH(Int_t index, TObjArray *list, TObjArray *trigArr, Bool_t keepOriginal=kFALSE)
Int_t FillData(TObjArray **list, Int_t index, double x)
Bool_t IsValidEventSpecie(Int_t eventSpecieIndex, TObjArray **list)
static TObjArray * fgCloningRequest
static TFile * GetQAResultFile()
Definition: AliQAv1.cxx:456
Int_t GetEvCountTotal(AliRecoParam::EventSpecie_t sp, AliQAv1::TASKINDEX_t task, Int_t trCl=-1) const
Char_t * GetHistoTrigger(const TH1 *h) const
Float_t p[]
Definition: kNNTest.C:133
Int_t SetDataBinError(TObjArray **list, Int_t index, int bin, double err)
void ResetEvCountCycle()
Int_t GetEvCountCycle(AliRecoParam::EventSpecie_t sp, AliQAv1::TASKINDEX_t task, Int_t trCl=-1) const
static void ResetEventTrigClasses()
static TObjArray * GetDataOfTrigClass(TObjArray *arr, Int_t cloneID, TObjArray *dest=0)
Int_t SetDataBinContent(TObjArray **list, Int_t index, int bin, double w)
#define AliInfoClass(message)
Definition: AliLog.h:489
TArrayI fEvCountTotal[AliRecoParam::kNSpecies]
TClonesArray * fDigitsArray
event specie, see AliRecoParam
TString fDetectorDirName
directory for the given detector in the file
virtual void InitRaws()=0
void IncEvCountTotal(AliQAv1::TASKINDEX_t task, Int_t diff=1)
#define AliErrorClass(message)
Definition: AliLog.h:596
static DETECTORINDEX_t GetDetIndex(const char *name)
Definition: AliQAv1.cxx:348
virtual void ClonePerTrigClassL(TObjArray **list, AliQAv1::TASKINDEX_t task)
static Bool_t IsEventTriggerSet()
static TObjArray fgEventTrigClasses
static Int_t GetNEventTrigClasses()
TObject * GetData(TObjArray **list, const Int_t index)
static EventSpecie_t ConvertIndex(Int_t index)
virtual void InitDigits()=0
char * prefix
virtual ~AliQADataMaker()
Int_t ResetStatsData(TObjArray **list, Int_t index)
virtual void InitRecPoints()=0
#define AliWarningClass(message)
Definition: AliLog.h:546
static TNamed * GetEventTrigClass(Int_t i)
void ResetEvCountTotal()
void rec(const char *filename="raw.root")
Definition: rec.C:1
TObjArray * GetMatchingHistosSet(TObjArray **list, const Int_t *indexList, Int_t nHist, Int_t trigId)
TArrayI fEvCountCycle[AliRecoParam::kNSpecies]
array to hold the sdigits
static Int_t GetNTrigClasses()
TH1 * GetMatchingHisto(TObjArray **list, Int_t index, Int_t trigId)
virtual void InitHits()=0
virtual void DefaultEndOfDetectorCycle(AliQAv1::TASKINDEX_t task)
static Int_t SetEventTrigClasses(const char *triggers)
virtual TObjArray ** Init(AliQAv1::TASKINDEX_t, Int_t cycles=-1)=0
static UInt_t GetClonedBit()
Definition: AliQAv1.h:85
#define AliDebug(logLevel, message)
Definition: AliLog.h:300
void Set(QABIT_t bit, AliRecoParam::EventSpecie_t es)
Definition: AliQAv1.cxx:763
Int_t ResetData(TObjArray **list, Int_t index, Option_t *option="")
TASKINDEX_t
Definition: AliQAv1.h:30
AliQADataMaker(const Char_t *name="", const Char_t *title="")
Int_t Add2List(TH1 *hist, const Int_t index, TObjArray **list, const Bool_t expert=kFALSE, const Bool_t image=kFALSE, const Bool_t saveForCorr=kFALSE)
#define AliError(message)
Definition: AliLog.h:591
static const char * GetQAName()
Definition: AliQAv1.h:73
static Int_t AConvert(EventSpecie_t es)
static Int_t GetQADebugLevel()
Definition: AliQAv1.h:72
TObjArray * GetMatchingHistos(TObjArray **list, Int_t index, TObjArray *optDest=0)
virtual void InitSDigits()=0
static TString GetTaskName(UInt_t tsk)
Definition: AliQAv1.h:90
AliRecoParam::EventSpecie_t fEventSpecie
run number
virtual void InitESDs()=0
static AliQAv1 * Instance()
Definition: AliQAv1.cxx:585
Bool_t IsCloningForbidden(TH1 *h) const