Added possibility of using * wildcard in histo names to clone (Diego)
[u/mrichter/AliRoot.git] / STEER / STEER / AliQADataMaker.cxx
CommitLineData
421ab0fb 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
202374b1 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//
421ab0fb 25
26// --- ROOT system ---
eca4fa66 27#include <TROOT.h>
421ab0fb 28#include <TSystem.h>
29#include <TFile.h>
6c18591a 30#include <TList.h>
d76c31f4 31#include <TTree.h>
d5cf81bd 32#include <TClonesArray.h>
a2b64fbd 33#include <TParameter.h>
57acd2d2 34#include <TH1K.h>
35#include <TH2C.h>
92664bc8 36#include <TH2F.h>
57acd2d2 37#include <TH2F.h>
38#include <TH2I.h>
39#include <TH3C.h>
92664bc8 40#include <TH3F.h>
57acd2d2 41#include <TH3F.h>
42#include <TH3I.h>
43#include <TH3S.h>
92664bc8 44#include <TArrayI.h>
45#include <TPRegexp.h>
421ab0fb 46// --- Standard library ---
47
48// --- AliRoot header files ---
49#include "AliLog.h"
2e42b4d4 50#include "AliQADataMaker.h"
51#include "AliQAChecker.h"
d76c31f4 52#include "AliESDEvent.h"
d5cf81bd 53#include "AliRawReader.h"
5e232cd6 54#include "AliDetectorRecoParam.h"
55
421ab0fb 56
2e42b4d4 57ClassImp(AliQADataMaker)
92664bc8 58
59const Char_t* AliQADataMaker::fgkTriggerPrefix = "_$TR$_";
60TObjArray* AliQADataMaker::fgCloningRequest = 0;
61TObjArray* AliQADataMaker::fgTrigClasses = 0;
62TObjArray AliQADataMaker::fgEventTrigClasses;
63
421ab0fb 64//____________________________________________________________________________
fec0891b 65AliQADataMaker::AliQADataMaker(const Char_t * name, const Char_t * title) :
421ab0fb 66 TNamed(name, title),
67 fOutput(0x0),
6c18591a 68 fDetectorDir(0x0),
312e6f8d 69 fDetectorDirName(""),
930e6e3e 70 fCurrentCycle(0),
5b188f2f 71 fCycle(9999999),
72 fCycleCounter(0),
b1af1125 73 fWriteExpert(kFALSE),
57acd2d2 74 fParameterList(new TList*[AliRecoParam::kNSpecies]),
75 fRun(0),
71f27f1f 76 fEventSpecie(AliRecoParam::kDefault),
6252ceeb 77 fDigitsArray(NULL)
421ab0fb 78{
79 // ctor
421ab0fb 80 fDetectorDirName = GetName() ;
92664bc8 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
421ab0fb 87}
88
89//____________________________________________________________________________
2e42b4d4 90AliQADataMaker::AliQADataMaker(const AliQADataMaker& qadm) :
421ab0fb 91 TNamed(qadm.GetName(), qadm.GetTitle()),
92 fOutput(qadm.fOutput),
6c18591a 93 fDetectorDir(qadm.fDetectorDir),
312e6f8d 94 fDetectorDirName(qadm.fDetectorDirName),
5b188f2f 95 fCurrentCycle(qadm.fCurrentCycle),
96 fCycle(qadm.fCycle),
97 fCycleCounter(qadm.fCycleCounter),
b1af1125 98 fWriteExpert(qadm.fWriteExpert),
a2b64fbd 99 fParameterList(qadm.fParameterList),
57acd2d2 100 fRun(qadm.fRun),
634696f5 101 fEventSpecie(qadm.fEventSpecie),
6252ceeb 102 fDigitsArray(NULL)
421ab0fb 103{
104 //copy ctor
105 fDetectorDirName = GetName() ;
eca4fa66 106 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
107 fParameterList[specie] = qadm.fParameterList[specie] ;
92664bc8 108 fEvCountCycle[specie] = qadm.fEvCountCycle[specie];
109 fEvCountTotal[specie] = qadm.fEvCountTotal[specie];
110 // fImage[specie] = qadm.fImage[specie] ;
eca4fa66 111 }
421ab0fb 112}
113
71f27f1f 114//____________________________________________________________________________
115AliQADataMaker::~AliQADataMaker()
116{
117 for (Int_t esIndex = 0 ; esIndex < AliRecoParam::kNSpecies ; esIndex++) {
71f27f1f 118 if (fParameterList[esIndex] )
119 delete fParameterList[esIndex] ;
120 }
71f27f1f 121 delete[] fParameterList ;
6252ceeb 122 if (fDigitsArray) {
123 fDigitsArray->Clear() ;
124 delete fDigitsArray ;
125 }
71f27f1f 126}
127
ba7aca7d 128//____________________________________________________________________________
7d297381 129Int_t AliQADataMaker::Add2List(TH1 * hist, const Int_t index, TObjArray ** list, const Bool_t expert, const Bool_t image, const Bool_t saveForCorr)
ba7aca7d 130{
92664bc8 131 // Set histograms memory resident and add to the list
132 // Maximm allowed is 10000
57acd2d2 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())) ;
92664bc8 139 } else if ( index > AliQAv1::GetMaxQAObj() ) {
140 AliError(Form("Max number of authorized QA objects is %d", AliQAv1::GetMaxQAObj())) ;
eca4fa66 141 } else {
92664bc8 142 hist->SetDirectory(0);
750730d8 143 if (expert)
7d297381 144 hist->SetBit(AliQAv1::GetExpertBit()) ;
145 if (image)
146 hist->SetBit(AliQAv1::GetImageBit()) ;
eca4fa66 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) ;
152 if ( fParameterList[AliRecoParam::AConvert(fEventSpecie)] == NULL )
fcab16e6 153 {
eca4fa66 154 fParameterList[AliRecoParam::AConvert(fEventSpecie)] = new TList() ;
a5ef5a9a 155 // fParameterList[AliRecoParam::AConvert(fEventSpecie)]->SetOwner(kTRUE);
fcab16e6 156 }
eca4fa66 157 fParameterList[AliRecoParam::AConvert(fEventSpecie)]->Add(p) ;
a2b64fbd 158 }
8db8be00 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 }
eca4fa66 164 list[AliRecoParam::AConvert(fEventSpecie)]->AddAtAndExpand(hist, index) ;
165 rv = list[AliRecoParam::AConvert(fEventSpecie)]->GetLast() ;
a2b64fbd 166 }
57acd2d2 167 return rv ;
168}
169
92664bc8 170//____________________________________________________________________________
171void AliQADataMaker::ClonePerTrigClassL(TObjArray ** list, AliQAv1::TASKINDEX_t task)
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
175 int spec = AliRecoParam::AConvert(fEventSpecie);
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//____________________________________________________________________________
204Int_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 }
b53824c8 254 else if ( histPatt.Contains("*") ) {
255 histPatt.ReplaceAll("*",".*");
256 histPatt.Prepend('^'); histPatt += "$";
257 cloneMany = kTRUE;
258 }
92664bc8 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 {
b53824c8 272 if ( hname.CompareTo(histPatt) ) continue;
92664bc8 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//____________________________________________________________________________
286Int_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//____________________________________________________________________________
336Char_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//____________________________________________________________________________
347Int_t AliQADataMaker::SetEventTrigClasses(const char* triggers)
348{
349 // sets the array of triggers fired in given event, return the number of triggers
350 //
351 ResetEventTrigClasses();
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 return 0;
360 }
361 int nTrClasses = 0;
362 for (int ial=fgTrigClasses->GetEntriesFast();ial--;) {
363 TNamed *pair = (TNamed*)fgTrigClasses->At(ial);
364 TString triggSet = pair->GetTitle(); // list of trigger names
365 for (int itr=nTrigs;itr--;) {
366 if ( !triggSet.Contains(tarr->At(itr)->GetName()) ) continue;
367 fgEventTrigClasses.Add(pair);
368 nTrClasses++;
369 break;
370 }
371 }
372 //
373 fgEventTrigClasses.SetOwner(kFALSE);
374 delete tarr;
375 //
376 return nTrClasses;
377}
378
379//____________________________________________________________________________
380TH1* AliQADataMaker::GetMatchingHisto(TObjArray ** list, Int_t index, Int_t trigId)
381{
382 // get histo with given index matching to trigId-th current trigger class
383 // trigId < 0 means default hist (only if cloning was done)
384 TObject* data = GetData(list,index);
385 if (!data) return 0;
386 if (trigId<0 || trigId==GetNEventTrigClasses()) { // original histo is requested
387 if (!data->TestBit(AliQAv1::GetClonedBit())) return (TH1*)data; // was not cloned per trigger
388 // check if during the cloning the original histo was kept (always at slot GetNTrigClasses())
389 else if (data->TestBit(AliQAv1::GetOrigHistoKeptBit())) return (TH1*)((TObjArray*)data)->At(GetNTrigClasses());
390 return 0;
391 }
392 //
393 if (!data->TestBit(AliQAv1::GetClonedBit())) return 0; // no cloning was done
394 if (trigId>GetNEventTrigClasses()) {
395 AliError(Form("Current event has %d triggers only, %d-th is requested",GetNEventTrigClasses(),trigId));
396 return 0; // invalid trigger
397 }
398 int slot = fgEventTrigClasses.At(trigId)->GetUniqueID(); // the histos are at slots corresponding to trig.class ID
399 return (TH1*)((TObjArray*)data)->At(slot);
400 //
401}
402
403//____________________________________________________________________________
404TObjArray* AliQADataMaker::GetMatchingHistosSet(TObjArray ** list, const Int_t* indexList, Int_t nHist, Int_t trigId)
405{
406 // get set of nHist histos with indices from the indexList matching to trigId-th current trigger
407 // Note: a static array is returned, it will be overwritten at the next call
408 static TObjArray garr;
409 garr.Clear();
410 for (int ih=0;ih<nHist;ih++) {
411 TH1* histo = GetMatchingHisto(list, indexList[ih],trigId);
412 if (!histo) return 0; // if at least 1 histo is not found, return nothing
413 garr.Add(histo);
414 }
415 return &garr;
416}
417
418//____________________________________________________________________________
419Bool_t AliQADataMaker::CheckCloningConsistency(TObjArray ** list, const Int_t* indexList, Int_t nHist, Bool_t checkTriggers)
420{
421 // Make sure that histograms at slots mentioned in the indexList are either
422 // not cloned per trigger or
423 // cloned for the same amount of triggers and if original histo was kept, then it is done for all histos.
424 // If checkTriggers is requested, apart from clones count also the trigger names are checked
425 //
426 // This consistency check is needed to ensure validity of the operations over the group of histograms in the EndOfDetectorCycle's
427 //
428 TObjArray* refArr = 0;
429 int refSlot = -1;
430 for (int isl=0;isl<nHist;isl++) {
431 int slot = indexList[isl];
432 TObject* data = GetData(list,slot);
433 if (!data) {AliError(Form("Slot %d is not booked",slot)); return kFALSE;}
434 //
435 if (refSlot<0) { // just take the 1st mentioned slot as a reference;
436 if (data->TestBit(AliQAv1::GetClonedBit())) refArr = (TObjArray*) data; // data was cloned
437 refSlot = slot;
438 continue;
439 }
440 //
441 if (!data->TestBit(AliQAv1::GetClonedBit())) { // this slot is not cloned, compare with reference
442 if (refArr) {AliError(Form("Slot %d is not cloned, slot %d is cloned",slot, refSlot)); return kFALSE;}
443 else continue;
444 }
445 //
446 TObjArray* currArr = (TObjArray*) data; // current slot is cloned
447 if (!refArr) {AliError(Form("Slot %d is not cloned, slot %d is cloned",refSlot,slot)); return kFALSE;}
448 //
449 // both are cloned
450 if (refArr->GetEntriesFast()!=currArr->GetEntriesFast()) {
451 AliError(Form("Different number of clones: slot %d: %d vs slot %d: %d",
452 refSlot,refArr->GetEntriesFast(), slot,currArr->GetEntriesFast()));
453 return kFALSE;
454 }
455 //
456 if (refArr->TestBit(AliQAv1::GetOrigHistoKeptBit())!=currArr->TestBit(AliQAv1::GetOrigHistoKeptBit())) {
457 AliError(Form("Slot %d kept original histo, slot %d did not",
458 refArr->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? refSlot:slot,refArr->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? slot:refSlot));
459 return kFALSE;
460 }
461 //
462 if (checkTriggers) {
463 for (int ih=refArr->GetEntriesFast();ih--;) {
464 TH1* hRef = (TH1*)refArr->At(ih);
465 if (!hRef->TestBit(AliQAv1::GetClonedBit())) continue; // original histo was kept, no trigger name is expected
466 TString hnm = ((TH1*)currArr->At(ih))->GetName();
467 if (!hnm.EndsWith( GetHistoTrigger(hRef) )) {
468 AliError(Form("Slots %d and %d have different trigger names for clone %d: %s vs %s",
469 refSlot,slot,ih,hRef->GetName(),hnm.Data()));
470 return kFALSE;
471 }
472 }
473 }
474 }
475 //
476 return kTRUE;
477}
478
479//____________________________________________________________________________
480TObjArray* AliQADataMaker::GetMatchingHistos(TObjArray ** list, Int_t index, TObjArray* optDest)
481{
482 // return all histograms of given index matching to any trigger in the current event trigger's list
483 // If the destination optDest is provided - use it, otherwise fill/return own static array
484 // In the latter case one should be careful: the content is overwritten at each call
485 // If the original histo was cloned but kept, it is also returned
486 //
487 // Note: if there are no triggers set, all eventual clones are returned
488 // (used for EndOfDetectorCycle loop over all histos)
489 static TObjArray garr;
490 TObjArray *dest = optDest ? optDest : &garr;
491 dest->SetOwner(kFALSE);
492 dest->Clear();
493 TObject* data = GetData(list,index);
494 if (!data) return 0;
495 if (!data->TestBit(AliQAv1::GetClonedBit())) dest->AddLast(data); // not cloned per trigger
496 else {
497 TObjArray* arr = dynamic_cast<TObjArray*>(data);
f00a510a 498 if (!arr) return 0;
92664bc8 499 if (IsEventTriggerSet()) {
500 int ncl = GetNEventTrigClasses();
501 for (int icl=0;icl<ncl;icl++) {
502 int indCl = GetEventTrigClass(icl)->GetUniqueID();
503 // AliInfo(Form("Ind %d at %d of %p of %p",index,indCl, arr, list[AliRecoParam::AConvert(fEventSpecie)]));
504 TH1* histo = dynamic_cast<TH1*>(arr->At(indCl));
505 dest->AddLast(histo);
506 // AliInfo(Form("EvCl%d IndTr%d add to %d IndH %d %p %s",icl,indCl,dest->LastIndex(),index,histo,histo ? histo->GetName():"XXX"));
507 }
508 // check if original histo was kept
509 if (arr->TestBit(AliQAv1::GetOrigHistoKeptBit())) {
510 TH1* histo = dynamic_cast<TH1*>(arr->At(GetNTrigClasses()));
511 dest->AddLast(histo);
512 // AliInfo(Form("Def add to %d inex: %d %p %s",dest->LastIndex(),index,histo,histo ? histo->GetName():"XXX"));
513 }
514 }
515 else { // trigger is not set, return all clones
516 for (int ih=arr->GetEntriesFast();ih--;) if (arr->At(ih)) dest->AddLast(arr->At(ih));
517 }
518 }
519 return dest;
520}
521
522//____________________________________________________________________________
523Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x)
524{
525 // fills single histo or its trigger-dependent clones, return number of histos filled
526 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 527 int count = 0;
528 if (arr) {
529 count = arr->GetEntriesFast();
530 for (int ih=count;ih--;) ((TH1*)arr->At(ih))->Fill(x);
531 }
92664bc8 532 return count;
533}
534
535//____________________________________________________________________________
536Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x, double y)
537{
538 // fills single histo or its trigger-dependent clones, return number of histos filled
539 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 540 int count = 0;
541 if (arr) {
542 count = arr->GetEntriesFast();
543 for (int ih=count;ih--;) ((TH1*)arr->At(ih))->Fill(x,y);
544 }
92664bc8 545 return count;
546}
547
548//____________________________________________________________________________
549Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x, double y, double z)
550{
551 // fills single histo or its trigger-dependent clones, return number of histos filled
552 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 553 int count = 0;
554 if (arr) {
555 count = arr->GetEntriesFast();
556 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->Fill(x,y,z);
557 }
92664bc8 558 return count;
559}
560
561//____________________________________________________________________________
562Int_t AliQADataMaker::SetDataBinContent(TObjArray ** list, Int_t index, int bin, double w)
563{
564 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
565 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 566 int count = 0;
567 if (arr) {
568 count = arr->GetEntriesFast();
569 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinContent(bin,w);
570 }
92664bc8 571 return count;
572}
573
574//____________________________________________________________________________
575Int_t AliQADataMaker::SetDataBinContent(TObjArray ** list, Int_t index, int binX, int binY, double w)
576{
577 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
578 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 579 int count = 0;
580 if (arr) {
581 count = arr->GetEntriesFast();
582 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinContent(binX,binY,w);
583 }
92664bc8 584 return count;
585}
586
587//____________________________________________________________________________
588Int_t AliQADataMaker::SetDataBinError(TObjArray ** list, Int_t index, int bin, double err)
589{
590 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
591 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 592 int count = 0;
593 if (arr) {
594 count = arr->GetEntriesFast();
595 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinError(bin,err);
596 }
92664bc8 597 return count;
598}
599
600//____________________________________________________________________________
601Int_t AliQADataMaker::SetDataBinError(TObjArray ** list, Int_t index, int binX, int binY, double err)
602{
603 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
604 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 605 int count = 0;
606 if (arr) {
607 count = arr->GetEntriesFast();
608 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinError(binX,binY,err);
609 }
92664bc8 610 return count;
611}
612
613//____________________________________________________________________________
614Int_t AliQADataMaker::ResetData(TObjArray ** list, Int_t index, Option_t* option)
615{
616 // reset content of single histo or its trigger-dependent clones, return number of histos processed
617 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 618 int count = 0;
619 if (arr) {
620 count = arr->GetEntriesFast();
621 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->Reset(option);
622 }
92664bc8 623 return count;
624}
625
626//____________________________________________________________________________
627Int_t AliQADataMaker::ResetStatsData(TObjArray ** list, Int_t index)
628{
629 // reset stats of single histo or its trigger-dependent clones, return number of histos processed
630 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 631 int count = 0;
632 if (arr) {
633 count = arr->GetEntriesFast();
634 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->ResetStats();
635 }
92664bc8 636 return count;
637}
638
57acd2d2 639//____________________________________________________________________________
640TH1 * AliQADataMaker::CloneMe(TH1 * hist, Int_t specie) const
641{
642 // clones a histogram
fec0891b 643 const Char_t * name = Form("%s_%s", AliRecoParam::GetEventSpecieName(specie), hist->GetName()) ;
eca4fa66 644 TH1 * hClone = static_cast<TH1 *>(hist->Clone(name)) ;
4e25ac79 645 if ( hist->TestBit(AliQAv1::GetExpertBit()) )
b2db43c5 646 hClone->SetBit(AliQAv1::GetExpertBit()) ;
647 if ( hist->TestBit(AliQAv1::GetImageBit()) )
648 hClone->SetBit(AliQAv1::GetImageBit()) ;
75373542 649 return hClone ;
421ab0fb 650}
651
96d67a8d 652//____________________________________________________________________________
4e25ac79 653void AliQADataMaker::DefaultEndOfDetectorCycle(AliQAv1::TASKINDEX_t task)
96d67a8d 654{
92664bc8 655 // this method must be oveloaded by detectors
656 // sets the QA result to Fatal
657 AliQAv1::Instance(AliQAv1::GetDetIndex(GetName())) ;
658 AliQAv1 * qa = AliQAv1::Instance(task) ;
57acd2d2 659 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
4e25ac79 660 qa->Set(AliQAv1::kFATAL, specie) ;
92664bc8 661 AliQAv1::GetQAResultFile()->cd() ;
662 qa->Write(AliQAv1::GetQAName(), kWriteDelete) ;
663 AliQAv1::GetQAResultFile()->Close() ;
96d67a8d 664}
665
421ab0fb 666//____________________________________________________________________________
c65c502a 667void AliQADataMaker::Finish() const
421ab0fb 668{
92664bc8 669 // write to the output File
670 if (fOutput)
671 fOutput->Close() ;
421ab0fb 672}
673
92664bc8 674//____________________________________________________________________________
675TH1* AliQADataMaker::GetData(TObjArray ** list, const Int_t index, int cloneID)
676{
677 // get the cloneID-th clone of the histo, -1 for original (if kept)
678 TObject* data = GetData(list,index);
679 if (!data) return 0;
680 Bool_t orig = cloneID<0 || cloneID==GetNTrigClasses();
681 if (data->TestBit(AliQAv1::GetClonedBit())) {
682 if (orig) return data->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? (TH1*)((TObjArray*)data)->At(GetNTrigClasses()) : 0;
683 else return (TH1*)((TObjArray*)data)->At(cloneID); // there was a cloning
684 }
685 //
686 // not cloned, is the original histo requested?
687 if (cloneID<0 || cloneID==GetNTrigClasses()) return (TH1*)data;
688 return 0;
689 //
690}
691
692//____________________________________________________________________________
693TObjArray* AliQADataMaker::GetDataOfTrigClass(TObjArray ** list, Int_t specieIndex, int cloneID, TObjArray *dest)
694{
695 // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
696 // a single array (if dest is not provided, use its own static array).
697 // Existing histos are attached at their original positions
a5ef5a9a 698 if (!list) return 0x0;
92664bc8 699 TObjArray* arr = list[specieIndex] ;
700 return GetDataOfTrigClass(arr, cloneID, dest);
701}
702
703//____________________________________________________________________________
704TObjArray* AliQADataMaker::GetDataOfTrigClass(TObjArray *arr, int cloneID, TObjArray *dest)
705{
706 // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
707 // a single array (if dest is not provided, use its own static array).
708 // Existing histos are attached at their original positions
709 static TObjArray arrTransf;
710 TObjArray* destS = dest ? dest : &arrTransf;
711 destS->SetOwner(kFALSE);
712 destS->Clear();
713 if (arr) {
714 Bool_t orig = cloneID<0 || cloneID==GetNTrigClasses(); // is trigger-blind histo requested?
715 int nh = arr->GetEntriesFast();
716 if (nh>destS->GetSize()) destS->Expand(nh);
717 for (int ih=nh;ih--;) {
718 TObject* ob = arr->At(ih);
719 if (!ob) continue;
720 //
721 if (ob->TestBit(AliQAv1::GetClonedBit())) { // this is array of cloned histos
722 if (orig) ob = ob->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? ((TObjArray*)ob)->At(GetNTrigClasses()) : 0;
723 else ob = ((TObjArray*)ob)->At(cloneID);
724 }
725 else if (!orig) ob = 0; // histogram was not cloned but the clone is requested
726 if (!ob) continue;
727 (*destS)[ih] = ob;
728 }
b96186e7 729 destS->SetUniqueID(arr->GetUniqueID());
92664bc8 730 }
731 return destS;
732 //
733}
734
735//____________________________________________________________________________
736TObjArray* AliQADataMaker::GetDataOfTrigClass(TObjArray ** list, int cloneID, TObjArray *dest)
737{
738 // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
739 // a single array (if dest is not provided, use its own static array).
740 // Existing histos are attached at their original positions
741 //
742 GetData(list,0); //just to initialize, if needed
743 Int_t esindex = AliRecoParam::AConvert(fEventSpecie);
744 return GetDataOfTrigClass(list, esindex, cloneID, dest);
745 //
746}
747
421ab0fb 748//____________________________________________________________________________
57acd2d2 749TObject * AliQADataMaker::GetData(TObjArray ** list, const Int_t index)
04236e67 750{
92664bc8 751 // Returns the QA object at index. Limit is AliQAv1::GetMaxQAObj()
76c42cb4 752 if ( ! list ) {
92664bc8 753 AliError("Data list is NULL !!") ;
754 return NULL ;
755 }
eca4fa66 756 Int_t esindex = AliRecoParam::AConvert(fEventSpecie) ;
92664bc8 757 TObject* histClone = NULL ;
49466ea2 758 TObjArray * arr = list[esindex] ;
92664bc8 759 if (arr) {
6252ceeb 760 if ( ! arr->GetEntriesFast() ) {
761 // Initializes the histograms
762 TString arrName(arr->GetName()) ;
763 if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kRAWS)))
764 InitRaws() ;
765 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kHITS)))
766 InitHits() ;
767 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kSDIGITS)))
768 InitSDigits() ;
769 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kDIGITS)))
770 InitDigits() ;
771 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kDIGITSR)))
7f0f88e7 772 InitDigits() ;
6252ceeb 773 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kRECPOINTS)))
774 InitRecPoints() ;
775 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kESDS)))
776 InitESDs() ;
777 }
92664bc8 778 if ( index > AliQAv1::GetMaxQAObj() ) {
779 AliError(Form("Max number of authorized QA objects is %d", AliQAv1::GetMaxQAObj())) ;
780 } else {
49466ea2 781 if ( arr->At(index) ) {
92664bc8 782 histClone = arr->At(index);
eca4fa66 783 }
784 }
785 }
786 return histClone ;
27773260 787}
7d297381 788
211a7313 789//____________________________________________________________________________
790TObjArray* AliQADataMaker::Init(AliQAv1::TASKINDEX_t task, AliRecoParam::EventSpecie_t es, Int_t cycles)
791{
792 // Initialializes and returns the QAData list for a given event specie
793 TObjArray ** ar = Init(task, cycles) ;
794 return ar[AliRecoParam::AConvert(es)] ;
795}
796
6252ceeb 797//____________________________________________________________________________
798Bool_t AliQADataMaker::IsValidEventSpecie(Int_t eventSpecieIndex, TObjArray ** list)
799{
800 // check if event specie was present in current run or
801 // if histograms of this event specie have been created
802 if (! AliQAv1::Instance(AliQAv1::GetDetIndex(GetName()))->IsEventSpecieSet(AliRecoParam::ConvertIndex(eventSpecieIndex)) || ! list[eventSpecieIndex]->GetEntriesFast() )
803 return kFALSE ;
804 else
805 return kTRUE ;
806}
9ac91920 807
92664bc8 808//____________________________________________________________________________
809void AliQADataMaker::SetCloningRequest(TObjArray* aliases, TObjArray* histos)
810{
811 // set associations {trigger names} <-> {trigger class alias}
812 //
813 const UInt_t kDummyID = 0xffff;
814 //
815 if (fgTrigClasses || fgCloningRequest) {
816 AliWarningClass("Cloning request is already set");
817 return;
818 }
819 ResetEventTrigClasses();
820 if (!aliases || !histos) {
821 AliWarningClass("Cloning request is incomplete");
822 return;
823 }
824 fgTrigClasses = aliases;
825 fgCloningRequest = histos;
826 //
827 // flag those aliases which are actually used
828 fgCloningRequest->Compress();
829 fgTrigClasses->Compress();
830 int nalias = fgTrigClasses->GetEntriesFast();
831 int nhisto = fgCloningRequest->GetEntriesFast();
832 //
833 int naliasUsed = 0;
834 for (int ial=0;ial<nalias;ial++) {
835 TNamed* alias = (TNamed*)fgTrigClasses->At(ial);
836 alias->SetUniqueID(kDummyID);
837 TString aliasName = alias->GetName();
838 for (int ih=nhisto;ih--;) {
839 TNamed* histo = (TNamed*)fgCloningRequest->At(ih);
840 TString histoReq = histo->GetTitle(); // list of aliases for which the histo must be cloned
841 TObjArray* alList = histoReq.Tokenize(" ");
842 if (!alList) continue;
843 for (int iha=alList->GetEntriesFast();iha--;) {
844 if (!(aliasName == alList->At(iha)->GetName())) continue;
845 alias->SetUniqueID(naliasUsed++); // acknowledge used alias
846 break;
847 }
848 if (alias->GetUniqueID()!=kDummyID) break; // once alias is validated, check the next one
849 }
850 }
851 // eliminate unused aliases
852 for (int ial=0;ial<nalias;ial++) if (fgTrigClasses->At(ial)->GetUniqueID()==kDummyID) delete fgTrigClasses->RemoveAt(ial);
853 fgTrigClasses->Compress();
854 //
855 AliInfoClass("Aliases for trigger classes:");
856 for (int i=0;i<fgTrigClasses->GetEntriesFast();i++) {
857 TNamed* item = (TNamed*)fgTrigClasses->At(i);
858 AliInfoClass(Form("%s -> %s",item->GetName(),item->GetTitle()));
859 }
860 //
861 AliInfoClass("Histograms to clone:");
862 for (int i=0;i<fgCloningRequest->GetEntriesFast();i++) {
863 TNamed* item = (TNamed*)fgCloningRequest->At(i);
864 AliInfoClass(Form("%s -> %s %s",item->GetName(),item->GetTitle(),
865 item->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? " + TriggerBlind":""));
866 }
867 //
868}
869
870//____________________________________________________________________________
871void AliQADataMaker::IncEvCountCycle(AliQAv1::TASKINDEX_t task, Int_t diff)
872{
873 // incerment by "diff" the cycle counters for the current event trigger classes (+ the global one)
874 int ncl = GetNTrigClasses();
875 int isp = AliRecoParam::AConvert(fEventSpecie);
876 //
877 if (fEvCountCycle[isp].GetSize()==AliQAv1::kNTASKINDEX && ncl>0) fEvCountCycle[isp].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
878 //
879 fEvCountCycle[isp][task*(1+ncl)+ncl] += diff; // trigger independent counter
880 for (int icl=GetNEventTrigClasses();icl--;) fEvCountCycle[isp][task*(1+ncl)+ GetEventTrigClass(icl)->GetUniqueID()] += diff;
881}
882
883//____________________________________________________________________________
884void AliQADataMaker::IncEvCountTotal(AliQAv1::TASKINDEX_t task, Int_t diff)
885{
886 // incerment by "diff" the cycle counters for the current event trigger classes (+ the global one)
887 int ncl = GetNTrigClasses();
888 int isp = AliRecoParam::AConvert(fEventSpecie);
889 //
890 if (fEvCountTotal[isp].GetSize()==AliQAv1::kNTASKINDEX && ncl>0) fEvCountTotal[isp].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
891 //
892 fEvCountTotal[isp][task*(1+ncl)+ncl] += diff; // trigger independent counter
893 for (int icl=GetNEventTrigClasses();icl--;) fEvCountTotal[isp][task*(1+ncl)+ GetEventTrigClass(icl)->GetUniqueID()] += diff;
894}
895
896//____________________________________________________________________________
897void AliQADataMaker::ResetEvCountCycle(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task)
898{
899 // reset counter for specific trigger class for specific specie (within the cycle)
900 int ncl = GetNTrigClasses();
901 // check if it was already expanded
902 if (fEvCountCycle[isp].GetSize()==AliQAv1::kNTASKINDEX) fEvCountCycle[isp].Set(AliQAv1::kNTASKINDEX*(ncl+1));
903 for (int icl=ncl+1;icl--;) fEvCountCycle[AliRecoParam::AConvert(isp)][task*(1+ncl) + icl] = 0;
904}
905
906//____________________________________________________________________________
907void AliQADataMaker::ResetEvCountTotal(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task)
908{
909 // reset counter for specific trigger class for specific specie (global count)
910 int ncl = GetNTrigClasses();
911 // check if it was already expanded
912 if (fEvCountTotal[isp].GetSize()==AliQAv1::kNTASKINDEX) fEvCountTotal[isp].Set(AliQAv1::kNTASKINDEX*(ncl+1));
913 for (int icl=ncl+1;icl--;) fEvCountTotal[AliRecoParam::AConvert(isp)][task*(1+ncl) + icl] = 0;
914}
915
916//____________________________________________________________________________
917Int_t AliQADataMaker::GetEvCountCycle(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task, Int_t trCl) const
918{
919 // get counter for specific trigger class for specific specie (within the cycle)
920 int ncl = GetNTrigClasses();
921 return fEvCountCycle[AliRecoParam::AConvert(isp)][task*(1+ncl) + (trCl<0||trCl>=ncl ? ncl:trCl)];
922}
923//____________________________________________________________________________
924Int_t AliQADataMaker::GetEvCountTotal(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task, Int_t trCl) const
925{
926 // get counter for specific trigger class for specific specie (global count)
927 int ncl = GetNTrigClasses();
928 return fEvCountTotal[AliRecoParam::AConvert(isp)][task*(1+ncl) + (trCl<0||trCl>=ncl ? ncl:trCl)];
929}
930