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