Coverity fix
[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 }
254 }
255 //
256 int nCloned = 0;
257 for (int ih=0;ih<nh;ih++) {
258 TH1* hist = (TH1*)list->At(ih);
259 if (!hist) continue;
260 if (!cloneAll) {
261 TString hname = hist->GetName();
262 if (cloneMany) {
263 TPRegexp patPR(histPatt);
264 if ( !hname.Contains(patPR) ) continue;
265 }
266 else {
267 if ( !hname.Contains(histPatt) ) continue;
268 }
269 }
270 //
271 // histo name matches, clone it
272 nCloned += ClonePerTrigClassH(ih, list, trigArr, keepOriginal);
273 if (!cloneMany) break; // no wildcards, just one histo is expected
274 }
275 //
276 delete trigArr;
277 return nCloned;
278}
279
280//____________________________________________________________________________
281Int_t AliQADataMaker::ClonePerTrigClassH(Int_t index, TObjArray* list, TObjArray* trigArr, Bool_t keepOriginal)
282{
283 // substitute the histogram at position index by the TObjArray containing clones of
284 // original histogram for each trigger from the trigArr
285 // When keepOriginal is requested, the original histo is not deleted and filled for each trigger
286 TH1* hist = (TH1*) list->At(index);
287 if (!hist) return 0; // should never happen, checked in calling method
288
289 if (IsCloningForbidden(hist)) {
290 AliError(Form("Cloning per trigger is forbidden for histo %s at slot %d",hist->GetName(),index));
291 return 0;
292 }
293 //
294 if (hist->TestBit(AliQAv1::GetClonedBit())) {
295 AliError(Form("histo %s at slot %d was already cloned!",((TObjArray*)hist)->GetName(),index));
296 return 0;
297 }
298 //
299 int nTrigs = trigArr->GetEntriesFast();
300 TObjArray* clonesArr = new TObjArray(GetNTrigClasses()+keepOriginal);
301 // transfer the user bits of the histo to be cloned to array
302 for (int ib=14;ib<=23;ib++) if (hist->TestBit(1<<ib)) clonesArr->SetBit(1<<ib);
303 //
304 if (keepOriginal) {
305 clonesArr->AddAt(hist,GetNTrigClasses());
306 clonesArr->SetBit(AliQAv1::GetOrigHistoKeptBit());
307 }
308 clonesArr->SetBit(AliQAv1::GetClonedBit());
309 clonesArr->SetName(hist->GetName());
310 for (int itr=0;itr<nTrigs;itr++) {
311 TObject* trigClass = trigArr->At(itr);
312 TH1* hclone = (TH1*)hist->Clone(Form("%s%s%s",hist->GetName(), fgkTriggerPrefix, trigClass->GetName()));
313 hclone->SetTitle(Form("%s %s",hist->GetTitle(), trigClass->GetName()));
314 hclone->SetDirectory(hist->GetDirectory());
315 //
316 // NOTE: the clone is added at position corresponding to ID of the trigger alias
317 clonesArr->AddAt(hclone, trigClass->GetUniqueID());
318 hclone->SetBit(AliQAv1::GetClonedBit());
319 AliDebug(AliQAv1::GetQADebugLevel(),Form("Cloned histogram %s for trigger class %s",hist->GetName(),trigClass->GetName()));
320 }
321 //
322 list->RemoveAt(index); // remove original histogram
323 list->AddAt(clonesArr, index);
324 if (!keepOriginal) delete hist;
325 //
326 clonesArr->SetOwner(kTRUE);
327 return clonesArr->GetEntries();
328}
329
330//____________________________________________________________________________
331Char_t* AliQADataMaker::GetHistoTrigger(const TH1* h) const
332{
333 // extract the name of the trigger from the histogram name
334 if (!h || !h->TestBit(AliQAv1::GetClonedBit())) return 0;
335 TString hnm = h->GetName();
336 int idx = hnm.Index(fgkTriggerPrefix);
337 if (idx<0) return 0; // not cloned
338 return (char*) h->GetName() + idx + sizeof(fgkTriggerPrefix) - 1;
339}
340
341//____________________________________________________________________________
342Int_t AliQADataMaker::SetEventTrigClasses(const char* triggers)
343{
344 // sets the array of triggers fired in given event, return the number of triggers
345 //
346 ResetEventTrigClasses();
347 fgEventTrigClasses.SetUniqueID(1); // flag that this is a triggered event
348 if (!GetNTrigClasses()) return 0; // meaningless if the trigger aliases are not set
349 TString trigStr = triggers;
350 TObjArray* tarr = trigStr.Tokenize(" ");
351 int nTrigs = tarr->GetEntriesFast();
352 if (!nTrigs) {
353 AliWarningClass("The string for event triggers is empty");
354 return 0;
355 }
356 int nTrClasses = 0;
357 for (int ial=fgTrigClasses->GetEntriesFast();ial--;) {
358 TNamed *pair = (TNamed*)fgTrigClasses->At(ial);
359 TString triggSet = pair->GetTitle(); // list of trigger names
360 for (int itr=nTrigs;itr--;) {
361 if ( !triggSet.Contains(tarr->At(itr)->GetName()) ) continue;
362 fgEventTrigClasses.Add(pair);
363 nTrClasses++;
364 break;
365 }
366 }
367 //
368 fgEventTrigClasses.SetOwner(kFALSE);
369 delete tarr;
370 //
371 return nTrClasses;
372}
373
374//____________________________________________________________________________
375TH1* AliQADataMaker::GetMatchingHisto(TObjArray ** list, Int_t index, Int_t trigId)
376{
377 // get histo with given index matching to trigId-th current trigger class
378 // trigId < 0 means default hist (only if cloning was done)
379 TObject* data = GetData(list,index);
380 if (!data) return 0;
381 if (trigId<0 || trigId==GetNEventTrigClasses()) { // original histo is requested
382 if (!data->TestBit(AliQAv1::GetClonedBit())) return (TH1*)data; // was not cloned per trigger
383 // check if during the cloning the original histo was kept (always at slot GetNTrigClasses())
384 else if (data->TestBit(AliQAv1::GetOrigHistoKeptBit())) return (TH1*)((TObjArray*)data)->At(GetNTrigClasses());
385 return 0;
386 }
387 //
388 if (!data->TestBit(AliQAv1::GetClonedBit())) return 0; // no cloning was done
389 if (trigId>GetNEventTrigClasses()) {
390 AliError(Form("Current event has %d triggers only, %d-th is requested",GetNEventTrigClasses(),trigId));
391 return 0; // invalid trigger
392 }
393 int slot = fgEventTrigClasses.At(trigId)->GetUniqueID(); // the histos are at slots corresponding to trig.class ID
394 return (TH1*)((TObjArray*)data)->At(slot);
395 //
396}
397
398//____________________________________________________________________________
399TObjArray* AliQADataMaker::GetMatchingHistosSet(TObjArray ** list, const Int_t* indexList, Int_t nHist, Int_t trigId)
400{
401 // get set of nHist histos with indices from the indexList matching to trigId-th current trigger
402 // Note: a static array is returned, it will be overwritten at the next call
403 static TObjArray garr;
404 garr.Clear();
405 for (int ih=0;ih<nHist;ih++) {
406 TH1* histo = GetMatchingHisto(list, indexList[ih],trigId);
407 if (!histo) return 0; // if at least 1 histo is not found, return nothing
408 garr.Add(histo);
409 }
410 return &garr;
411}
412
413//____________________________________________________________________________
414Bool_t AliQADataMaker::CheckCloningConsistency(TObjArray ** list, const Int_t* indexList, Int_t nHist, Bool_t checkTriggers)
415{
416 // Make sure that histograms at slots mentioned in the indexList are either
417 // not cloned per trigger or
418 // cloned for the same amount of triggers and if original histo was kept, then it is done for all histos.
419 // If checkTriggers is requested, apart from clones count also the trigger names are checked
420 //
421 // This consistency check is needed to ensure validity of the operations over the group of histograms in the EndOfDetectorCycle's
422 //
423 TObjArray* refArr = 0;
424 int refSlot = -1;
425 for (int isl=0;isl<nHist;isl++) {
426 int slot = indexList[isl];
427 TObject* data = GetData(list,slot);
428 if (!data) {AliError(Form("Slot %d is not booked",slot)); return kFALSE;}
429 //
430 if (refSlot<0) { // just take the 1st mentioned slot as a reference;
431 if (data->TestBit(AliQAv1::GetClonedBit())) refArr = (TObjArray*) data; // data was cloned
432 refSlot = slot;
433 continue;
434 }
435 //
436 if (!data->TestBit(AliQAv1::GetClonedBit())) { // this slot is not cloned, compare with reference
437 if (refArr) {AliError(Form("Slot %d is not cloned, slot %d is cloned",slot, refSlot)); return kFALSE;}
438 else continue;
439 }
440 //
441 TObjArray* currArr = (TObjArray*) data; // current slot is cloned
442 if (!refArr) {AliError(Form("Slot %d is not cloned, slot %d is cloned",refSlot,slot)); return kFALSE;}
443 //
444 // both are cloned
445 if (refArr->GetEntriesFast()!=currArr->GetEntriesFast()) {
446 AliError(Form("Different number of clones: slot %d: %d vs slot %d: %d",
447 refSlot,refArr->GetEntriesFast(), slot,currArr->GetEntriesFast()));
448 return kFALSE;
449 }
450 //
451 if (refArr->TestBit(AliQAv1::GetOrigHistoKeptBit())!=currArr->TestBit(AliQAv1::GetOrigHistoKeptBit())) {
452 AliError(Form("Slot %d kept original histo, slot %d did not",
453 refArr->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? refSlot:slot,refArr->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? slot:refSlot));
454 return kFALSE;
455 }
456 //
457 if (checkTriggers) {
458 for (int ih=refArr->GetEntriesFast();ih--;) {
459 TH1* hRef = (TH1*)refArr->At(ih);
460 if (!hRef->TestBit(AliQAv1::GetClonedBit())) continue; // original histo was kept, no trigger name is expected
461 TString hnm = ((TH1*)currArr->At(ih))->GetName();
462 if (!hnm.EndsWith( GetHistoTrigger(hRef) )) {
463 AliError(Form("Slots %d and %d have different trigger names for clone %d: %s vs %s",
464 refSlot,slot,ih,hRef->GetName(),hnm.Data()));
465 return kFALSE;
466 }
467 }
468 }
469 }
470 //
471 return kTRUE;
472}
473
474//____________________________________________________________________________
475TObjArray* AliQADataMaker::GetMatchingHistos(TObjArray ** list, Int_t index, TObjArray* optDest)
476{
477 // return all histograms of given index matching to any trigger in the current event trigger's list
478 // If the destination optDest is provided - use it, otherwise fill/return own static array
479 // In the latter case one should be careful: the content is overwritten at each call
480 // If the original histo was cloned but kept, it is also returned
481 //
482 // Note: if there are no triggers set, all eventual clones are returned
483 // (used for EndOfDetectorCycle loop over all histos)
484 static TObjArray garr;
485 TObjArray *dest = optDest ? optDest : &garr;
486 dest->SetOwner(kFALSE);
487 dest->Clear();
488 TObject* data = GetData(list,index);
489 if (!data) return 0;
490 if (!data->TestBit(AliQAv1::GetClonedBit())) dest->AddLast(data); // not cloned per trigger
491 else {
492 TObjArray* arr = dynamic_cast<TObjArray*>(data);
f00a510a 493 if (!arr) return 0;
92664bc8 494 if (IsEventTriggerSet()) {
495 int ncl = GetNEventTrigClasses();
496 for (int icl=0;icl<ncl;icl++) {
497 int indCl = GetEventTrigClass(icl)->GetUniqueID();
498 // AliInfo(Form("Ind %d at %d of %p of %p",index,indCl, arr, list[AliRecoParam::AConvert(fEventSpecie)]));
499 TH1* histo = dynamic_cast<TH1*>(arr->At(indCl));
500 dest->AddLast(histo);
501 // AliInfo(Form("EvCl%d IndTr%d add to %d IndH %d %p %s",icl,indCl,dest->LastIndex(),index,histo,histo ? histo->GetName():"XXX"));
502 }
503 // check if original histo was kept
504 if (arr->TestBit(AliQAv1::GetOrigHistoKeptBit())) {
505 TH1* histo = dynamic_cast<TH1*>(arr->At(GetNTrigClasses()));
506 dest->AddLast(histo);
507 // AliInfo(Form("Def add to %d inex: %d %p %s",dest->LastIndex(),index,histo,histo ? histo->GetName():"XXX"));
508 }
509 }
510 else { // trigger is not set, return all clones
511 for (int ih=arr->GetEntriesFast();ih--;) if (arr->At(ih)) dest->AddLast(arr->At(ih));
512 }
513 }
514 return dest;
515}
516
517//____________________________________________________________________________
518Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x)
519{
520 // fills single histo or its trigger-dependent clones, return number of histos filled
521 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 522 int count = 0;
523 if (arr) {
524 count = arr->GetEntriesFast();
525 for (int ih=count;ih--;) ((TH1*)arr->At(ih))->Fill(x);
526 }
92664bc8 527 return count;
528}
529
530//____________________________________________________________________________
531Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x, double y)
532{
533 // fills single histo or its trigger-dependent clones, return number of histos filled
534 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 535 int count = 0;
536 if (arr) {
537 count = arr->GetEntriesFast();
538 for (int ih=count;ih--;) ((TH1*)arr->At(ih))->Fill(x,y);
539 }
92664bc8 540 return count;
541}
542
543//____________________________________________________________________________
544Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x, double y, double z)
545{
546 // fills single histo or its trigger-dependent clones, return number of histos filled
547 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 548 int count = 0;
549 if (arr) {
550 count = arr->GetEntriesFast();
551 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->Fill(x,y,z);
552 }
92664bc8 553 return count;
554}
555
556//____________________________________________________________________________
557Int_t AliQADataMaker::SetDataBinContent(TObjArray ** list, Int_t index, int bin, double w)
558{
559 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
560 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 561 int count = 0;
562 if (arr) {
563 count = arr->GetEntriesFast();
564 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinContent(bin,w);
565 }
92664bc8 566 return count;
567}
568
569//____________________________________________________________________________
570Int_t AliQADataMaker::SetDataBinContent(TObjArray ** list, Int_t index, int binX, int binY, double w)
571{
572 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
573 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 574 int count = 0;
575 if (arr) {
576 count = arr->GetEntriesFast();
577 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinContent(binX,binY,w);
578 }
92664bc8 579 return count;
580}
581
582//____________________________________________________________________________
583Int_t AliQADataMaker::SetDataBinError(TObjArray ** list, Int_t index, int bin, double err)
584{
585 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
586 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 587 int count = 0;
588 if (arr) {
589 count = arr->GetEntriesFast();
590 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinError(bin,err);
591 }
92664bc8 592 return count;
593}
594
595//____________________________________________________________________________
596Int_t AliQADataMaker::SetDataBinError(TObjArray ** list, Int_t index, int binX, int binY, double err)
597{
598 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
599 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 600 int count = 0;
601 if (arr) {
602 count = arr->GetEntriesFast();
603 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinError(binX,binY,err);
604 }
92664bc8 605 return count;
606}
607
608//____________________________________________________________________________
609Int_t AliQADataMaker::ResetData(TObjArray ** list, Int_t index, Option_t* option)
610{
611 // reset content of single histo or its trigger-dependent clones, return number of histos processed
612 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 613 int count = 0;
614 if (arr) {
615 count = arr->GetEntriesFast();
616 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->Reset(option);
617 }
92664bc8 618 return count;
619}
620
621//____________________________________________________________________________
622Int_t AliQADataMaker::ResetStatsData(TObjArray ** list, Int_t index)
623{
624 // reset stats of single histo or its trigger-dependent clones, return number of histos processed
625 TObjArray* arr = GetMatchingHistos(list,index);
a5ef5a9a 626 int count = 0;
627 if (arr) {
628 count = arr->GetEntriesFast();
629 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->ResetStats();
630 }
92664bc8 631 return count;
632}
633
57acd2d2 634//____________________________________________________________________________
635TH1 * AliQADataMaker::CloneMe(TH1 * hist, Int_t specie) const
636{
637 // clones a histogram
fec0891b 638 const Char_t * name = Form("%s_%s", AliRecoParam::GetEventSpecieName(specie), hist->GetName()) ;
eca4fa66 639 TH1 * hClone = static_cast<TH1 *>(hist->Clone(name)) ;
4e25ac79 640 if ( hist->TestBit(AliQAv1::GetExpertBit()) )
b2db43c5 641 hClone->SetBit(AliQAv1::GetExpertBit()) ;
642 if ( hist->TestBit(AliQAv1::GetImageBit()) )
643 hClone->SetBit(AliQAv1::GetImageBit()) ;
75373542 644 return hClone ;
421ab0fb 645}
646
96d67a8d 647//____________________________________________________________________________
4e25ac79 648void AliQADataMaker::DefaultEndOfDetectorCycle(AliQAv1::TASKINDEX_t task)
96d67a8d 649{
92664bc8 650 // this method must be oveloaded by detectors
651 // sets the QA result to Fatal
652 AliQAv1::Instance(AliQAv1::GetDetIndex(GetName())) ;
653 AliQAv1 * qa = AliQAv1::Instance(task) ;
57acd2d2 654 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
4e25ac79 655 qa->Set(AliQAv1::kFATAL, specie) ;
92664bc8 656 AliQAv1::GetQAResultFile()->cd() ;
657 qa->Write(AliQAv1::GetQAName(), kWriteDelete) ;
658 AliQAv1::GetQAResultFile()->Close() ;
96d67a8d 659}
660
421ab0fb 661//____________________________________________________________________________
c65c502a 662void AliQADataMaker::Finish() const
421ab0fb 663{
92664bc8 664 // write to the output File
665 if (fOutput)
666 fOutput->Close() ;
421ab0fb 667}
668
92664bc8 669//____________________________________________________________________________
670TH1* AliQADataMaker::GetData(TObjArray ** list, const Int_t index, int cloneID)
671{
672 // get the cloneID-th clone of the histo, -1 for original (if kept)
673 TObject* data = GetData(list,index);
674 if (!data) return 0;
675 Bool_t orig = cloneID<0 || cloneID==GetNTrigClasses();
676 if (data->TestBit(AliQAv1::GetClonedBit())) {
677 if (orig) return data->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? (TH1*)((TObjArray*)data)->At(GetNTrigClasses()) : 0;
678 else return (TH1*)((TObjArray*)data)->At(cloneID); // there was a cloning
679 }
680 //
681 // not cloned, is the original histo requested?
682 if (cloneID<0 || cloneID==GetNTrigClasses()) return (TH1*)data;
683 return 0;
684 //
685}
686
687//____________________________________________________________________________
688TObjArray* AliQADataMaker::GetDataOfTrigClass(TObjArray ** list, Int_t specieIndex, int cloneID, TObjArray *dest)
689{
690 // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
691 // a single array (if dest is not provided, use its own static array).
692 // Existing histos are attached at their original positions
a5ef5a9a 693 if (!list) return 0x0;
92664bc8 694 TObjArray* arr = list[specieIndex] ;
695 return GetDataOfTrigClass(arr, cloneID, dest);
696}
697
698//____________________________________________________________________________
699TObjArray* AliQADataMaker::GetDataOfTrigClass(TObjArray *arr, int cloneID, TObjArray *dest)
700{
701 // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
702 // a single array (if dest is not provided, use its own static array).
703 // Existing histos are attached at their original positions
704 static TObjArray arrTransf;
705 TObjArray* destS = dest ? dest : &arrTransf;
706 destS->SetOwner(kFALSE);
707 destS->Clear();
708 if (arr) {
709 Bool_t orig = cloneID<0 || cloneID==GetNTrigClasses(); // is trigger-blind histo requested?
710 int nh = arr->GetEntriesFast();
711 if (nh>destS->GetSize()) destS->Expand(nh);
712 for (int ih=nh;ih--;) {
713 TObject* ob = arr->At(ih);
714 if (!ob) continue;
715 //
716 if (ob->TestBit(AliQAv1::GetClonedBit())) { // this is array of cloned histos
717 if (orig) ob = ob->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? ((TObjArray*)ob)->At(GetNTrigClasses()) : 0;
718 else ob = ((TObjArray*)ob)->At(cloneID);
719 }
720 else if (!orig) ob = 0; // histogram was not cloned but the clone is requested
721 if (!ob) continue;
722 (*destS)[ih] = ob;
723 }
b96186e7 724 destS->SetUniqueID(arr->GetUniqueID());
92664bc8 725 }
726 return destS;
727 //
728}
729
730//____________________________________________________________________________
731TObjArray* AliQADataMaker::GetDataOfTrigClass(TObjArray ** list, int cloneID, TObjArray *dest)
732{
733 // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
734 // a single array (if dest is not provided, use its own static array).
735 // Existing histos are attached at their original positions
736 //
737 GetData(list,0); //just to initialize, if needed
738 Int_t esindex = AliRecoParam::AConvert(fEventSpecie);
739 return GetDataOfTrigClass(list, esindex, cloneID, dest);
740 //
741}
742
421ab0fb 743//____________________________________________________________________________
57acd2d2 744TObject * AliQADataMaker::GetData(TObjArray ** list, const Int_t index)
04236e67 745{
92664bc8 746 // Returns the QA object at index. Limit is AliQAv1::GetMaxQAObj()
76c42cb4 747 if ( ! list ) {
92664bc8 748 AliError("Data list is NULL !!") ;
749 return NULL ;
750 }
eca4fa66 751 Int_t esindex = AliRecoParam::AConvert(fEventSpecie) ;
92664bc8 752 TObject* histClone = NULL ;
49466ea2 753 TObjArray * arr = list[esindex] ;
92664bc8 754 if (arr) {
6252ceeb 755 if ( ! arr->GetEntriesFast() ) {
756 // Initializes the histograms
757 TString arrName(arr->GetName()) ;
758 if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kRAWS)))
759 InitRaws() ;
760 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kHITS)))
761 InitHits() ;
762 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kSDIGITS)))
763 InitSDigits() ;
764 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kDIGITS)))
765 InitDigits() ;
766 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kDIGITSR)))
7f0f88e7 767 InitDigits() ;
6252ceeb 768 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kRECPOINTS)))
769 InitRecPoints() ;
770 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kESDS)))
771 InitESDs() ;
772 }
92664bc8 773 if ( index > AliQAv1::GetMaxQAObj() ) {
774 AliError(Form("Max number of authorized QA objects is %d", AliQAv1::GetMaxQAObj())) ;
775 } else {
49466ea2 776 if ( arr->At(index) ) {
92664bc8 777 histClone = arr->At(index);
eca4fa66 778 }
779 }
780 }
781 return histClone ;
27773260 782}
7d297381 783
211a7313 784//____________________________________________________________________________
785TObjArray* AliQADataMaker::Init(AliQAv1::TASKINDEX_t task, AliRecoParam::EventSpecie_t es, Int_t cycles)
786{
787 // Initialializes and returns the QAData list for a given event specie
788 TObjArray ** ar = Init(task, cycles) ;
789 return ar[AliRecoParam::AConvert(es)] ;
790}
791
6252ceeb 792//____________________________________________________________________________
793Bool_t AliQADataMaker::IsValidEventSpecie(Int_t eventSpecieIndex, TObjArray ** list)
794{
795 // check if event specie was present in current run or
796 // if histograms of this event specie have been created
797 if (! AliQAv1::Instance(AliQAv1::GetDetIndex(GetName()))->IsEventSpecieSet(AliRecoParam::ConvertIndex(eventSpecieIndex)) || ! list[eventSpecieIndex]->GetEntriesFast() )
798 return kFALSE ;
799 else
800 return kTRUE ;
801}
9ac91920 802
92664bc8 803//____________________________________________________________________________
804void AliQADataMaker::SetCloningRequest(TObjArray* aliases, TObjArray* histos)
805{
806 // set associations {trigger names} <-> {trigger class alias}
807 //
808 const UInt_t kDummyID = 0xffff;
809 //
810 if (fgTrigClasses || fgCloningRequest) {
811 AliWarningClass("Cloning request is already set");
812 return;
813 }
814 ResetEventTrigClasses();
815 if (!aliases || !histos) {
816 AliWarningClass("Cloning request is incomplete");
817 return;
818 }
819 fgTrigClasses = aliases;
820 fgCloningRequest = histos;
821 //
822 // flag those aliases which are actually used
823 fgCloningRequest->Compress();
824 fgTrigClasses->Compress();
825 int nalias = fgTrigClasses->GetEntriesFast();
826 int nhisto = fgCloningRequest->GetEntriesFast();
827 //
828 int naliasUsed = 0;
829 for (int ial=0;ial<nalias;ial++) {
830 TNamed* alias = (TNamed*)fgTrigClasses->At(ial);
831 alias->SetUniqueID(kDummyID);
832 TString aliasName = alias->GetName();
833 for (int ih=nhisto;ih--;) {
834 TNamed* histo = (TNamed*)fgCloningRequest->At(ih);
835 TString histoReq = histo->GetTitle(); // list of aliases for which the histo must be cloned
836 TObjArray* alList = histoReq.Tokenize(" ");
837 if (!alList) continue;
838 for (int iha=alList->GetEntriesFast();iha--;) {
839 if (!(aliasName == alList->At(iha)->GetName())) continue;
840 alias->SetUniqueID(naliasUsed++); // acknowledge used alias
841 break;
842 }
843 if (alias->GetUniqueID()!=kDummyID) break; // once alias is validated, check the next one
844 }
845 }
846 // eliminate unused aliases
847 for (int ial=0;ial<nalias;ial++) if (fgTrigClasses->At(ial)->GetUniqueID()==kDummyID) delete fgTrigClasses->RemoveAt(ial);
848 fgTrigClasses->Compress();
849 //
850 AliInfoClass("Aliases for trigger classes:");
851 for (int i=0;i<fgTrigClasses->GetEntriesFast();i++) {
852 TNamed* item = (TNamed*)fgTrigClasses->At(i);
853 AliInfoClass(Form("%s -> %s",item->GetName(),item->GetTitle()));
854 }
855 //
856 AliInfoClass("Histograms to clone:");
857 for (int i=0;i<fgCloningRequest->GetEntriesFast();i++) {
858 TNamed* item = (TNamed*)fgCloningRequest->At(i);
859 AliInfoClass(Form("%s -> %s %s",item->GetName(),item->GetTitle(),
860 item->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? " + TriggerBlind":""));
861 }
862 //
863}
864
865//____________________________________________________________________________
866void AliQADataMaker::IncEvCountCycle(AliQAv1::TASKINDEX_t task, Int_t diff)
867{
868 // incerment by "diff" the cycle counters for the current event trigger classes (+ the global one)
869 int ncl = GetNTrigClasses();
870 int isp = AliRecoParam::AConvert(fEventSpecie);
871 //
872 if (fEvCountCycle[isp].GetSize()==AliQAv1::kNTASKINDEX && ncl>0) fEvCountCycle[isp].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
873 //
874 fEvCountCycle[isp][task*(1+ncl)+ncl] += diff; // trigger independent counter
875 for (int icl=GetNEventTrigClasses();icl--;) fEvCountCycle[isp][task*(1+ncl)+ GetEventTrigClass(icl)->GetUniqueID()] += diff;
876}
877
878//____________________________________________________________________________
879void AliQADataMaker::IncEvCountTotal(AliQAv1::TASKINDEX_t task, Int_t diff)
880{
881 // incerment by "diff" the cycle counters for the current event trigger classes (+ the global one)
882 int ncl = GetNTrigClasses();
883 int isp = AliRecoParam::AConvert(fEventSpecie);
884 //
885 if (fEvCountTotal[isp].GetSize()==AliQAv1::kNTASKINDEX && ncl>0) fEvCountTotal[isp].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
886 //
887 fEvCountTotal[isp][task*(1+ncl)+ncl] += diff; // trigger independent counter
888 for (int icl=GetNEventTrigClasses();icl--;) fEvCountTotal[isp][task*(1+ncl)+ GetEventTrigClass(icl)->GetUniqueID()] += diff;
889}
890
891//____________________________________________________________________________
892void AliQADataMaker::ResetEvCountCycle(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task)
893{
894 // reset counter for specific trigger class for specific specie (within the cycle)
895 int ncl = GetNTrigClasses();
896 // check if it was already expanded
897 if (fEvCountCycle[isp].GetSize()==AliQAv1::kNTASKINDEX) fEvCountCycle[isp].Set(AliQAv1::kNTASKINDEX*(ncl+1));
898 for (int icl=ncl+1;icl--;) fEvCountCycle[AliRecoParam::AConvert(isp)][task*(1+ncl) + icl] = 0;
899}
900
901//____________________________________________________________________________
902void AliQADataMaker::ResetEvCountTotal(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task)
903{
904 // reset counter for specific trigger class for specific specie (global count)
905 int ncl = GetNTrigClasses();
906 // check if it was already expanded
907 if (fEvCountTotal[isp].GetSize()==AliQAv1::kNTASKINDEX) fEvCountTotal[isp].Set(AliQAv1::kNTASKINDEX*(ncl+1));
908 for (int icl=ncl+1;icl--;) fEvCountTotal[AliRecoParam::AConvert(isp)][task*(1+ncl) + icl] = 0;
909}
910
911//____________________________________________________________________________
912Int_t AliQADataMaker::GetEvCountCycle(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task, Int_t trCl) const
913{
914 // get counter for specific trigger class for specific specie (within the cycle)
915 int ncl = GetNTrigClasses();
916 return fEvCountCycle[AliRecoParam::AConvert(isp)][task*(1+ncl) + (trCl<0||trCl>=ncl ? ncl:trCl)];
917}
918//____________________________________________________________________________
919Int_t AliQADataMaker::GetEvCountTotal(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task, Int_t trCl) const
920{
921 // get counter for specific trigger class for specific specie (global count)
922 int ncl = GetNTrigClasses();
923 return fEvCountTotal[AliRecoParam::AConvert(isp)][task*(1+ncl) + (trCl<0||trCl>=ncl ? ncl:trCl)];
924}
925