]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/AliQADataMaker.cxx
Memory leaks fixed (L.Aphecetche and B.Rabacal)
[u/mrichter/AliRoot.git] / 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() ;
fcab16e6 155 fParameterList[AliRecoParam::AConvert(fEventSpecie)]->SetOwner(kTRUE);
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);
493 if (IsEventTriggerSet()) {
494 int ncl = GetNEventTrigClasses();
495 for (int icl=0;icl<ncl;icl++) {
496 int indCl = GetEventTrigClass(icl)->GetUniqueID();
497 // AliInfo(Form("Ind %d at %d of %p of %p",index,indCl, arr, list[AliRecoParam::AConvert(fEventSpecie)]));
498 TH1* histo = dynamic_cast<TH1*>(arr->At(indCl));
499 dest->AddLast(histo);
500 // AliInfo(Form("EvCl%d IndTr%d add to %d IndH %d %p %s",icl,indCl,dest->LastIndex(),index,histo,histo ? histo->GetName():"XXX"));
501 }
502 // check if original histo was kept
503 if (arr->TestBit(AliQAv1::GetOrigHistoKeptBit())) {
504 TH1* histo = dynamic_cast<TH1*>(arr->At(GetNTrigClasses()));
505 dest->AddLast(histo);
506 // AliInfo(Form("Def add to %d inex: %d %p %s",dest->LastIndex(),index,histo,histo ? histo->GetName():"XXX"));
507 }
508 }
509 else { // trigger is not set, return all clones
510 for (int ih=arr->GetEntriesFast();ih--;) if (arr->At(ih)) dest->AddLast(arr->At(ih));
511 }
512 }
513 return dest;
514}
515
516//____________________________________________________________________________
517Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x)
518{
519 // fills single histo or its trigger-dependent clones, return number of histos filled
520 TObjArray* arr = GetMatchingHistos(list,index);
521 int count = arr->GetEntriesFast();
522 for (int ih=count;ih--;) ((TH1*)arr->At(ih))->Fill(x);
523 return count;
524}
525
526//____________________________________________________________________________
527Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x, double y)
528{
529 // fills single histo or its trigger-dependent clones, return number of histos filled
530 TObjArray* arr = GetMatchingHistos(list,index);
531 int count = arr->GetEntriesFast();
532 for (int ih=count;ih--;) ((TH1*)arr->At(ih))->Fill(x,y);
533 return count;
534}
535
536//____________________________________________________________________________
537Int_t AliQADataMaker::FillData(TObjArray ** list, Int_t index, double x, double y, double z)
538{
539 // fills single histo or its trigger-dependent clones, return number of histos filled
540 TObjArray* arr = GetMatchingHistos(list,index);
541 int count = arr->GetEntriesFast();
542 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->Fill(x,y,z);
543 return count;
544}
545
546//____________________________________________________________________________
547Int_t AliQADataMaker::SetDataBinContent(TObjArray ** list, Int_t index, int bin, double w)
548{
549 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
550 TObjArray* arr = GetMatchingHistos(list,index);
551 int count = arr->GetEntriesFast();
552 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinContent(bin,w);
553 return count;
554}
555
556//____________________________________________________________________________
557Int_t AliQADataMaker::SetDataBinContent(TObjArray ** list, Int_t index, int binX, int binY, 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);
561 int count = arr->GetEntriesFast();
562 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinContent(binX,binY,w);
563 return count;
564}
565
566//____________________________________________________________________________
567Int_t AliQADataMaker::SetDataBinError(TObjArray ** list, Int_t index, int bin, double err)
568{
569 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
570 TObjArray* arr = GetMatchingHistos(list,index);
571 int count = arr->GetEntriesFast();
572 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinError(bin,err);
573 return count;
574}
575
576//____________________________________________________________________________
577Int_t AliQADataMaker::SetDataBinError(TObjArray ** list, Int_t index, int binX, int binY, double err)
578{
579 // set bin content of single histo or its trigger-dependent clones, return number of histos filled
580 TObjArray* arr = GetMatchingHistos(list,index);
581 int count = arr->GetEntriesFast();
582 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->SetBinError(binX,binY,err);
583 return count;
584}
585
586//____________________________________________________________________________
587Int_t AliQADataMaker::ResetData(TObjArray ** list, Int_t index, Option_t* option)
588{
589 // reset content of single histo or its trigger-dependent clones, return number of histos processed
590 TObjArray* arr = GetMatchingHistos(list,index);
591 int count = arr->GetEntriesFast();
592 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->Reset(option);
593 return count;
594}
595
596//____________________________________________________________________________
597Int_t AliQADataMaker::ResetStatsData(TObjArray ** list, Int_t index)
598{
599 // reset stats of single histo or its trigger-dependent clones, return number of histos processed
600 TObjArray* arr = GetMatchingHistos(list,index);
601 int count = arr->GetEntriesFast();
602 for (int ih=count;ih--;) ((TH2*)arr->At(ih))->ResetStats();
603 return count;
604}
605
57acd2d2 606//____________________________________________________________________________
607TH1 * AliQADataMaker::CloneMe(TH1 * hist, Int_t specie) const
608{
609 // clones a histogram
fec0891b 610 const Char_t * name = Form("%s_%s", AliRecoParam::GetEventSpecieName(specie), hist->GetName()) ;
eca4fa66 611 TH1 * hClone = static_cast<TH1 *>(hist->Clone(name)) ;
4e25ac79 612 if ( hist->TestBit(AliQAv1::GetExpertBit()) )
b2db43c5 613 hClone->SetBit(AliQAv1::GetExpertBit()) ;
614 if ( hist->TestBit(AliQAv1::GetImageBit()) )
615 hClone->SetBit(AliQAv1::GetImageBit()) ;
75373542 616 return hClone ;
421ab0fb 617}
618
96d67a8d 619//____________________________________________________________________________
4e25ac79 620void AliQADataMaker::DefaultEndOfDetectorCycle(AliQAv1::TASKINDEX_t task)
96d67a8d 621{
92664bc8 622 // this method must be oveloaded by detectors
623 // sets the QA result to Fatal
624 AliQAv1::Instance(AliQAv1::GetDetIndex(GetName())) ;
625 AliQAv1 * qa = AliQAv1::Instance(task) ;
57acd2d2 626 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
4e25ac79 627 qa->Set(AliQAv1::kFATAL, specie) ;
92664bc8 628 AliQAv1::GetQAResultFile()->cd() ;
629 qa->Write(AliQAv1::GetQAName(), kWriteDelete) ;
630 AliQAv1::GetQAResultFile()->Close() ;
96d67a8d 631}
632
421ab0fb 633//____________________________________________________________________________
c65c502a 634void AliQADataMaker::Finish() const
421ab0fb 635{
92664bc8 636 // write to the output File
637 if (fOutput)
638 fOutput->Close() ;
421ab0fb 639}
640
92664bc8 641//____________________________________________________________________________
642TH1* AliQADataMaker::GetData(TObjArray ** list, const Int_t index, int cloneID)
643{
644 // get the cloneID-th clone of the histo, -1 for original (if kept)
645 TObject* data = GetData(list,index);
646 if (!data) return 0;
647 Bool_t orig = cloneID<0 || cloneID==GetNTrigClasses();
648 if (data->TestBit(AliQAv1::GetClonedBit())) {
649 if (orig) return data->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? (TH1*)((TObjArray*)data)->At(GetNTrigClasses()) : 0;
650 else return (TH1*)((TObjArray*)data)->At(cloneID); // there was a cloning
651 }
652 //
653 // not cloned, is the original histo requested?
654 if (cloneID<0 || cloneID==GetNTrigClasses()) return (TH1*)data;
655 return 0;
656 //
657}
658
659//____________________________________________________________________________
660TObjArray* AliQADataMaker::GetDataOfTrigClass(TObjArray ** list, Int_t specieIndex, int cloneID, TObjArray *dest)
661{
662 // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
663 // a single array (if dest is not provided, use its own static array).
664 // Existing histos are attached at their original positions
665 TObjArray* arr = list[specieIndex] ;
666 return GetDataOfTrigClass(arr, cloneID, dest);
667}
668
669//____________________________________________________________________________
670TObjArray* AliQADataMaker::GetDataOfTrigClass(TObjArray *arr, int cloneID, TObjArray *dest)
671{
672 // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
673 // a single array (if dest is not provided, use its own static array).
674 // Existing histos are attached at their original positions
675 static TObjArray arrTransf;
676 TObjArray* destS = dest ? dest : &arrTransf;
677 destS->SetOwner(kFALSE);
678 destS->Clear();
679 if (arr) {
680 Bool_t orig = cloneID<0 || cloneID==GetNTrigClasses(); // is trigger-blind histo requested?
681 int nh = arr->GetEntriesFast();
682 if (nh>destS->GetSize()) destS->Expand(nh);
683 for (int ih=nh;ih--;) {
684 TObject* ob = arr->At(ih);
685 if (!ob) continue;
686 //
687 if (ob->TestBit(AliQAv1::GetClonedBit())) { // this is array of cloned histos
688 if (orig) ob = ob->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? ((TObjArray*)ob)->At(GetNTrigClasses()) : 0;
689 else ob = ((TObjArray*)ob)->At(cloneID);
690 }
691 else if (!orig) ob = 0; // histogram was not cloned but the clone is requested
692 if (!ob) continue;
693 (*destS)[ih] = ob;
694 }
695 }
696 return destS;
697 //
698}
699
700//____________________________________________________________________________
701TObjArray* AliQADataMaker::GetDataOfTrigClass(TObjArray ** list, int cloneID, TObjArray *dest)
702{
703 // get all histos for cloneID-th trigger class (-1 is for original "all-triggers" histos) in
704 // a single array (if dest is not provided, use its own static array).
705 // Existing histos are attached at their original positions
706 //
707 GetData(list,0); //just to initialize, if needed
708 Int_t esindex = AliRecoParam::AConvert(fEventSpecie);
709 return GetDataOfTrigClass(list, esindex, cloneID, dest);
710 //
711}
712
421ab0fb 713//____________________________________________________________________________
57acd2d2 714TObject * AliQADataMaker::GetData(TObjArray ** list, const Int_t index)
04236e67 715{
92664bc8 716 // Returns the QA object at index. Limit is AliQAv1::GetMaxQAObj()
76c42cb4 717 if ( ! list ) {
92664bc8 718 AliError("Data list is NULL !!") ;
719 return NULL ;
720 }
eca4fa66 721 Int_t esindex = AliRecoParam::AConvert(fEventSpecie) ;
92664bc8 722 TObject* histClone = NULL ;
49466ea2 723 TObjArray * arr = list[esindex] ;
92664bc8 724 if (arr) {
6252ceeb 725 if ( ! arr->GetEntriesFast() ) {
726 // Initializes the histograms
727 TString arrName(arr->GetName()) ;
728 if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kRAWS)))
729 InitRaws() ;
730 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kHITS)))
731 InitHits() ;
732 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kSDIGITS)))
733 InitSDigits() ;
734 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kDIGITS)))
735 InitDigits() ;
736 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kDIGITSR)))
7f0f88e7 737 InitDigits() ;
6252ceeb 738 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kRECPOINTS)))
739 InitRecPoints() ;
740 else if (arrName.Contains(AliQAv1::GetTaskName(AliQAv1::kESDS)))
741 InitESDs() ;
742 }
92664bc8 743 if ( index > AliQAv1::GetMaxQAObj() ) {
744 AliError(Form("Max number of authorized QA objects is %d", AliQAv1::GetMaxQAObj())) ;
745 } else {
49466ea2 746 if ( arr->At(index) ) {
92664bc8 747 histClone = arr->At(index);
eca4fa66 748 }
749 }
750 }
751 return histClone ;
27773260 752}
7d297381 753
211a7313 754//____________________________________________________________________________
755TObjArray* AliQADataMaker::Init(AliQAv1::TASKINDEX_t task, AliRecoParam::EventSpecie_t es, Int_t cycles)
756{
757 // Initialializes and returns the QAData list for a given event specie
758 TObjArray ** ar = Init(task, cycles) ;
759 return ar[AliRecoParam::AConvert(es)] ;
760}
761
6252ceeb 762//____________________________________________________________________________
763Bool_t AliQADataMaker::IsValidEventSpecie(Int_t eventSpecieIndex, TObjArray ** list)
764{
765 // check if event specie was present in current run or
766 // if histograms of this event specie have been created
767 if (! AliQAv1::Instance(AliQAv1::GetDetIndex(GetName()))->IsEventSpecieSet(AliRecoParam::ConvertIndex(eventSpecieIndex)) || ! list[eventSpecieIndex]->GetEntriesFast() )
768 return kFALSE ;
769 else
770 return kTRUE ;
771}
9ac91920 772
92664bc8 773//____________________________________________________________________________
774void AliQADataMaker::SetCloningRequest(TObjArray* aliases, TObjArray* histos)
775{
776 // set associations {trigger names} <-> {trigger class alias}
777 //
778 const UInt_t kDummyID = 0xffff;
779 //
780 if (fgTrigClasses || fgCloningRequest) {
781 AliWarningClass("Cloning request is already set");
782 return;
783 }
784 ResetEventTrigClasses();
785 if (!aliases || !histos) {
786 AliWarningClass("Cloning request is incomplete");
787 return;
788 }
789 fgTrigClasses = aliases;
790 fgCloningRequest = histos;
791 //
792 // flag those aliases which are actually used
793 fgCloningRequest->Compress();
794 fgTrigClasses->Compress();
795 int nalias = fgTrigClasses->GetEntriesFast();
796 int nhisto = fgCloningRequest->GetEntriesFast();
797 //
798 int naliasUsed = 0;
799 for (int ial=0;ial<nalias;ial++) {
800 TNamed* alias = (TNamed*)fgTrigClasses->At(ial);
801 alias->SetUniqueID(kDummyID);
802 TString aliasName = alias->GetName();
803 for (int ih=nhisto;ih--;) {
804 TNamed* histo = (TNamed*)fgCloningRequest->At(ih);
805 TString histoReq = histo->GetTitle(); // list of aliases for which the histo must be cloned
806 TObjArray* alList = histoReq.Tokenize(" ");
807 if (!alList) continue;
808 for (int iha=alList->GetEntriesFast();iha--;) {
809 if (!(aliasName == alList->At(iha)->GetName())) continue;
810 alias->SetUniqueID(naliasUsed++); // acknowledge used alias
811 break;
812 }
813 if (alias->GetUniqueID()!=kDummyID) break; // once alias is validated, check the next one
814 }
815 }
816 // eliminate unused aliases
817 for (int ial=0;ial<nalias;ial++) if (fgTrigClasses->At(ial)->GetUniqueID()==kDummyID) delete fgTrigClasses->RemoveAt(ial);
818 fgTrigClasses->Compress();
819 //
820 AliInfoClass("Aliases for trigger classes:");
821 for (int i=0;i<fgTrigClasses->GetEntriesFast();i++) {
822 TNamed* item = (TNamed*)fgTrigClasses->At(i);
823 AliInfoClass(Form("%s -> %s",item->GetName(),item->GetTitle()));
824 }
825 //
826 AliInfoClass("Histograms to clone:");
827 for (int i=0;i<fgCloningRequest->GetEntriesFast();i++) {
828 TNamed* item = (TNamed*)fgCloningRequest->At(i);
829 AliInfoClass(Form("%s -> %s %s",item->GetName(),item->GetTitle(),
830 item->TestBit(AliQAv1::GetOrigHistoKeptBit()) ? " + TriggerBlind":""));
831 }
832 //
833}
834
835//____________________________________________________________________________
836void AliQADataMaker::IncEvCountCycle(AliQAv1::TASKINDEX_t task, Int_t diff)
837{
838 // incerment by "diff" the cycle counters for the current event trigger classes (+ the global one)
839 int ncl = GetNTrigClasses();
840 int isp = AliRecoParam::AConvert(fEventSpecie);
841 //
842 if (fEvCountCycle[isp].GetSize()==AliQAv1::kNTASKINDEX && ncl>0) fEvCountCycle[isp].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
843 //
844 fEvCountCycle[isp][task*(1+ncl)+ncl] += diff; // trigger independent counter
845 for (int icl=GetNEventTrigClasses();icl--;) fEvCountCycle[isp][task*(1+ncl)+ GetEventTrigClass(icl)->GetUniqueID()] += diff;
846}
847
848//____________________________________________________________________________
849void AliQADataMaker::IncEvCountTotal(AliQAv1::TASKINDEX_t task, Int_t diff)
850{
851 // incerment by "diff" the cycle counters for the current event trigger classes (+ the global one)
852 int ncl = GetNTrigClasses();
853 int isp = AliRecoParam::AConvert(fEventSpecie);
854 //
855 if (fEvCountTotal[isp].GetSize()==AliQAv1::kNTASKINDEX && ncl>0) fEvCountTotal[isp].Set(AliQAv1::kNTASKINDEX*(GetNTrigClasses()+1)); // +1 for trigger-independent count
856 //
857 fEvCountTotal[isp][task*(1+ncl)+ncl] += diff; // trigger independent counter
858 for (int icl=GetNEventTrigClasses();icl--;) fEvCountTotal[isp][task*(1+ncl)+ GetEventTrigClass(icl)->GetUniqueID()] += diff;
859}
860
861//____________________________________________________________________________
862void AliQADataMaker::ResetEvCountCycle(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task)
863{
864 // reset counter for specific trigger class for specific specie (within the cycle)
865 int ncl = GetNTrigClasses();
866 // check if it was already expanded
867 if (fEvCountCycle[isp].GetSize()==AliQAv1::kNTASKINDEX) fEvCountCycle[isp].Set(AliQAv1::kNTASKINDEX*(ncl+1));
868 for (int icl=ncl+1;icl--;) fEvCountCycle[AliRecoParam::AConvert(isp)][task*(1+ncl) + icl] = 0;
869}
870
871//____________________________________________________________________________
872void AliQADataMaker::ResetEvCountTotal(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task)
873{
874 // reset counter for specific trigger class for specific specie (global count)
875 int ncl = GetNTrigClasses();
876 // check if it was already expanded
877 if (fEvCountTotal[isp].GetSize()==AliQAv1::kNTASKINDEX) fEvCountTotal[isp].Set(AliQAv1::kNTASKINDEX*(ncl+1));
878 for (int icl=ncl+1;icl--;) fEvCountTotal[AliRecoParam::AConvert(isp)][task*(1+ncl) + icl] = 0;
879}
880
881//____________________________________________________________________________
882Int_t AliQADataMaker::GetEvCountCycle(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task, Int_t trCl) const
883{
884 // get counter for specific trigger class for specific specie (within the cycle)
885 int ncl = GetNTrigClasses();
886 return fEvCountCycle[AliRecoParam::AConvert(isp)][task*(1+ncl) + (trCl<0||trCl>=ncl ? ncl:trCl)];
887}
888//____________________________________________________________________________
889Int_t AliQADataMaker::GetEvCountTotal(AliRecoParam::EventSpecie_t isp, AliQAv1::TASKINDEX_t task, Int_t trCl) const
890{
891 // get counter for specific trigger class for specific specie (global count)
892 int ncl = GetNTrigClasses();
893 return fEvCountTotal[AliRecoParam::AConvert(isp)][task*(1+ncl) + (trCl<0||trCl>=ncl ? ncl:trCl)];
894}
895