From ce0175fa20553397e1ed6d94b11231e8830329cb Mon Sep 17 00:00:00 2001 From: marian Date: Tue, 27 Oct 2009 11:00:34 +0000 Subject: [PATCH] AliTPCdataQA and AliTPCQADataMakerRec: QA update for DQM simplification and beautification. AliTPCQAChecker: Changes to close task 2475 - Implementation of reconstruction in QA checker (Peter Christiansen) --- TPC/AliTPCQAChecker.cxx | 286 +++++++++++++++++++++++++++++++++++ TPC/AliTPCQAChecker.h | 33 +++- TPC/AliTPCQADataMakerRec.cxx | 237 +++++++++++++++++++++++------ TPC/AliTPCQADataMakerRec.h | 18 ++- TPC/AliTPCdataQA.cxx | 135 ++++++++++++++++- TPC/AliTPCdataQA.h | 25 ++- 6 files changed, 672 insertions(+), 62 deletions(-) diff --git a/TPC/AliTPCQAChecker.cxx b/TPC/AliTPCQAChecker.cxx index 60df0d8fd5a..f510526dfc6 100644 --- a/TPC/AliTPCQAChecker.cxx +++ b/TPC/AliTPCQAChecker.cxx @@ -16,15 +16,301 @@ /* $Id: $ */ /* + Checks implemented a la AliMUONQAChecker. + Checks the quality assurance by realzed checks on histogram content. + P. Christiansen, Lund, September 2009. + Based on AliPHOSQAChecker. Checks the quality assurance by comparing with reference data. P. Christiansen, Lund, January 2008. */ +// --- ROOT header files --- +#include + // --- AliRoot header files --- #include "AliTPCQAChecker.h" +#include "AliTPCQADataMakerRec.h" ClassImp(AliTPCQAChecker) //__________________________________________________________________ +Double_t * +AliTPCQAChecker::Check(AliQAv1::ALITASK_t index, TObjArray ** list, + AliDetectorRecoParam * recoParam) +{ + /* It is important to understand the destinction between indexed tasks (AliQAv1::TASKINDEX_t) which are used in the DataMaker classes and indexed tasks (AliQAv1::ALITASK_t) whihc are used in the checker class. + + From the AliQAChecker::Run() methods we have: + AliQAv1::kRAW + - AliQAv1::kRAWS + + AliQAv1::kSIM + - AliQAv1::kHITS + - AliQAv1::kSDIGITS + - AliQAv1::kDIGITS + + AliQAv1::kREC + - AliQAv1::kDIGITSR + - AliQAv1::kRECPOINTS + - AliQAv1::kTRACKSEGMENTS + - AliQAv1::kRECPARTICLES + + AliQAv1::kESD ; + -AliQAv1::kESDS + + This means that for each group of tasks the Check will be called + one or more times. This also mean that we cannot know what + histograms will be or not be there in a single call... And we + also do not know the position in the list of the histogram. + */ + + /// Check objects in list + if(fDebug>0) + AliInfo("In AliTPCQAChecker::Check"); + + if (index!=AliQAv1::kRAW&&index!=AliQAv1::kREC&&index!=AliQAv1::kESD) { + + AliWarning(Form("Checker for task %d not implement for the moment",index)); + return NULL; + } + + Double_t * rv = new Double_t[AliRecoParam::kNSpecies] ; + for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) + rv[specie] = 1.0; // All is fine + + for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) { + + if ( !AliQAv1::Instance()->IsEventSpecieSet(specie) ) + continue ; + + if (index == AliQAv1::kRAW) + rv[specie] = CheckRAW(specie, list[specie]); + if (index == AliQAv1::kREC) + rv[specie] = CheckREC(specie, list[specie]); + if (index == AliQAv1::kESD) + rv[specie] = CheckESD(specie, list[specie]); + + if(fDebug>3) + AliInfo(Form("Specie: %s. Task: %s. Value: %f", + AliRecoParam::GetEventSpecieName(specie), + AliQAv1::GetAliTaskName(index), + rv[specie])); + } + + return rv; +} + +//______________________________________________________________________________ +Double_t AliTPCQAChecker::CheckRAW(Int_t specie, TObjArray* list) +{ + /// Check ESD + if(fDebug>0) + AliInfo("In AliTPCQAChecker::CheckRAW"); + + if(fDebug>2) + list->Print(); + + Char_t specieName[256]; + sprintf(specieName, AliRecoParam::GetEventSpecieName(specie)); + + TH1* hRawsOccupancyVsSector = static_cast + (list->FindObject(Form("%s_hRawsOccupancyVsSector",specieName))); + TH1* hRawsQmaxVsSector = static_cast + (list->FindObject(Form("%s_hRawsQmaxVsSector",specieName))); + TH1* hRawsOccupancyVsEvent = static_cast + (list->FindObject(Form("%s_hRawsOccupancyVsEvent",specieName))); + TH1* hRawsNclustersVsEvent = static_cast + (list->FindObject(Form("%s_hRawsNclustersVsEvent",specieName))); + + if (!hRawsOccupancyVsSector || !hRawsQmaxVsSector || + !hRawsOccupancyVsEvent || !hRawsNclustersVsEvent) + return -0.5; // fatal + + if(hRawsOccupancyVsSector->GetEntries()==0) { + return 0.25; // error - No TPC data! + } + + Int_t nBinsX = hRawsOccupancyVsSector->GetNbinsX(); + for(Int_t i = 1; i <= nBinsX; i++) { + + if(hRawsOccupancyVsSector->GetBinContent(i)==0) + return 0.75; // warning - no TPC data for at least one sector + } + + return 1.0; // ok +} + +//______________________________________________________________________________ +Double_t AliTPCQAChecker::CheckREC(Int_t specie, TObjArray* list) +{ + // This method checks the QA histograms associated with reconstruction + // + // For TPC this is: + // DigitsR : + // The digit histogram gives the ADC distribution for all sigbnals + // above threshold. The check is just that there are digits. + // RecPoints : + // The cluster histograms are meant to give an idea about the gain + // from the cluster charge and to indicate iof there are rows with + // noise clusters, i.e., they are very visual. + // + // The check methods are simple: + // If there are no histogram at all (set fatal) + // If digit histogram is there, but there are no digits (set error) + // If cluster histogram is there but there are less than 1000 + // clusters (set warning) + // If there are more than 1000 clusters but no clusters for either short, + // medium, or long pads (set error) + if(fDebug>0) + AliInfo("In AliTPCQAChecker::CheckREC"); + + if(fDebug>2) + list->Print(); + + Char_t specieName[256]; + sprintf(specieName, AliRecoParam::GetEventSpecieName(specie)); + + TH1* hDigits = static_cast + (list->FindObject(Form("%s_hDigitsADC",specieName))); + TH1* hNclustersVsRow = static_cast + (list->FindObject(Form("%s_hRecPointsRow",specieName))); + TH1* hQshort = static_cast + (list->FindObject(Form("%s_hRecPointsQShort",specieName))); + TH1* hQmedium = static_cast + (list->FindObject(Form("%s_hRecPointsQMedium",specieName))); + TH1* hQlong = static_cast + (list->FindObject(Form("%s_hRecPointsQLong",specieName))); + // The Qmax histograms are for now ignored + + if (!hDigits && // digits missing + (!hNclustersVsRow || !hQshort || !hQmedium || !hQlong)) // 1 recpoint hist missing + return -0.5; // fatal + + if (hDigits && hDigits->GetEntries()==0) + return 0.25; // error + + if (hNclustersVsRow && hNclustersVsRow->GetEntries() < 1000) { + return 0.75; // warning + } else { + if (!hQshort || !hQlong || !hQlong) + return -0.5;// fatal - they should be there if the cluster vs row hist is there + if (hQshort->GetEntries()==0 || hQmedium->GetEntries()==0 || + hQlong->GetEntries()==0) + return 0.25; // error + } + return 1; // ok +} + +//______________________________________________________________________________ +Double_t AliTPCQAChecker::CheckESD(Int_t specie, TObjArray* list) +{ + // This method checks the QA histograms associated with ESDs + // (Note that there is aslo a globalQA which is running on all + // the ESD information so for now this is just a few basic + // histograms) + // + // The check methods are simple: + // If there are no histogram at all (set fatal) + // + if(fDebug>0) + AliInfo("In AliTPCQAChecker::CheckESD"); + + if(fDebug>2) + list->Print(); + + Char_t specieName[256]; + sprintf(specieName, AliRecoParam::GetEventSpecieName(specie)); + + TH1* hESDclusters = static_cast + (list->FindObject(Form("%s_hESDclusters",specieName))); + TH1* hESDratio = static_cast + (list->FindObject(Form("%s_hESDratio",specieName))); + TH1* hESDpt = static_cast + (list->FindObject(Form("%s_hESDpt",specieName))); + + if (!hESDclusters || !hESDratio || !hESDpt) + return -0.5; // fatal + + return 1.0; // ok +} + +//______________________________________________________________________________ +void AliTPCQAChecker::Init(const AliQAv1::DETECTORINDEX_t det) +{ + /// intialises QA and QA checker settings + if(fDebug>0) + AliInfo("In AliTPCQAChecker::Init"); + AliQAv1::Instance(det) ; + Float_t hiValue[AliQAv1::kNBIT] ; + Float_t lowValue[AliQAv1::kNBIT] ; + hiValue[AliQAv1::kINFO] = 1.00; + lowValue[AliQAv1::kINFO] = 0.99; + hiValue[AliQAv1::kWARNING] = 0.99; + lowValue[AliQAv1::kWARNING] = 0.50; + hiValue[AliQAv1::kERROR] = 0.50; + lowValue[AliQAv1::kERROR] = 0.00; + hiValue[AliQAv1::kFATAL] = 0.00; + lowValue[AliQAv1::kFATAL] =-1.00; + // SetHiLo(&hiValue[0], &lowValue[0]) ; + SetHiLo(hiValue, lowValue) ; +} + +//______________________________________________________________________________ +void +AliTPCQAChecker::SetQA(AliQAv1::ALITASK_t index, Double_t * value) const +{ + /// sets the QA according the return value of the Check + + if(fDebug>0) + AliInfo("In AliTPCQAChecker::SetQA"); + + AliQAv1 * qa = AliQAv1::Instance(index); + + for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) { + if (value==NULL) { // No checker is implemented, set all QA to Fatal + + if(fDebug>1) + AliInfo(Form("Fatal QA. Task: %s. Specie: %s", + AliQAv1::GetAliTaskName(index), + AliRecoParam::GetEventSpecieName(specie))); + qa->Set(AliQAv1::kFATAL, specie) ; + } else { + + if ( value[specie] >= fLowTestValue[AliQAv1::kFATAL] && + value[specie] < fUpTestValue[AliQAv1::kFATAL] ) { + + if(fDebug>1) + AliInfo(Form("QA-Fatal. Task: %s. Specie: %s", + AliQAv1::GetAliTaskName(index), + AliRecoParam::GetEventSpecieName(specie))); + qa->Set(AliQAv1::kFATAL, specie) ; + } else if ( value[specie] > fLowTestValue[AliQAv1::kERROR] && + value[specie] <= fUpTestValue[AliQAv1::kERROR] ) { + + if(fDebug>1) + AliInfo(Form("QA-Error. Task: %s. Specie: %s", + AliQAv1::GetAliTaskName(index), + AliRecoParam::GetEventSpecieName(specie))); + qa->Set(AliQAv1::kERROR, specie) ; + } else if (value[specie] > fLowTestValue[AliQAv1::kWARNING] && + value[specie] <= fUpTestValue[AliQAv1::kWARNING]) { + + if(fDebug>1) + AliInfo(Form("QA-Warning. Task: %s. Specie: %s", + AliQAv1::GetAliTaskName(index), + AliRecoParam::GetEventSpecieName(specie))); + qa->Set(AliQAv1::kWARNING, specie) ; + } else if (value[specie] > fLowTestValue[AliQAv1::kINFO] && + value[specie] <= fUpTestValue[AliQAv1::kINFO] ) { + + if(fDebug>1) + AliInfo(Form("QA-Info. Task: %s. Specie: %s", + AliQAv1::GetAliTaskName(index), + AliRecoParam::GetEventSpecieName(specie))); + qa->Set(AliQAv1::kINFO, specie) ; + } + } + } +} diff --git a/TPC/AliTPCQAChecker.h b/TPC/AliTPCQAChecker.h index 52272d0c1db..f37b7d7ed94 100644 --- a/TPC/AliTPCQAChecker.h +++ b/TPC/AliTPCQAChecker.h @@ -7,24 +7,41 @@ /* $Id: $ */ /* - Based on AliPHOSQAChecker. - Checks the quality assurance by comparing with reference data. - P. Christiansen, Lund, January 2008. + Checks implemented a la AliMUONQAChecker. + Checks the quality assurance by very simple checks on histogram content. + P. Christiansen, Lund, September 2009. */ +// --- ROOT header files --- +#include + // --- AliRoot header files --- #include "AliQACheckerBase.h" +#include "AliDetectorRecoParam.h" class AliTPCQAChecker: public AliQACheckerBase { - -public: - AliTPCQAChecker() : AliQACheckerBase("TPC","TPC Quality Assurance Checker") {;} // ctor - AliTPCQAChecker(const AliTPCQAChecker& qac) : AliQACheckerBase(qac.GetName(), qac.GetTitle()) {;} // cpy ctor + + public: + AliTPCQAChecker() : AliQACheckerBase("TPC","TPC Quality Assurance Checker"), fDebug(0) {;} // ctor + AliTPCQAChecker(const AliTPCQAChecker& qac) : AliQACheckerBase(qac.GetName(), qac.GetTitle()), fDebug(qac.GetDebugLevel()) {;} // cpy ctor virtual ~AliTPCQAChecker() {;} // dtor + virtual Double_t * Check(AliQAv1::ALITASK_t, TObjArray **, AliDetectorRecoParam * recoParam); + void Init(const AliQAv1::DETECTORINDEX_t det); + void SetQA(AliQAv1::ALITASK_t index, Double_t * value) const; + + Int_t GetDebugLevel() const {return fDebug;} + void SetDebugLevel(Int_t value) {fDebug = value;} + private: - ClassDef(AliTPCQAChecker,1) // TPC Quality Assurance Checker + Double_t CheckRAW(Int_t specie, TObjArray* list); + Double_t CheckREC(Int_t specie, TObjArray* list); + Double_t CheckESD(Int_t specie, TObjArray* list); + + Int_t fDebug; + + ClassDef(AliTPCQAChecker,2) // TPC Quality Assurance Checker }; diff --git a/TPC/AliTPCQADataMakerRec.cxx b/TPC/AliTPCQADataMakerRec.cxx index 1188adc20b3..f49be1a2daa 100644 --- a/TPC/AliTPCQADataMakerRec.cxx +++ b/TPC/AliTPCQADataMakerRec.cxx @@ -51,6 +51,7 @@ #include #include #include +#include // --- Standard library --- @@ -69,9 +70,13 @@ ClassImp(AliTPCQADataMakerRec) //____________________________________________________________________________ AliTPCQADataMakerRec::AliTPCQADataMakerRec() : - AliQADataMakerRec(AliQAv1::GetDetName(AliQAv1::kTPC), - "TPC Rec Quality Assurance Data Maker"), - fTPCdataQA(NULL) +AliQADataMakerRec(AliQAv1::GetDetName(AliQAv1::kTPC), + "TPC Rec Quality Assurance Data Maker"), + fTPCdataQA(NULL), + fBeautifyOption(1), // 0:no beautify, !=0:beautify RAW + fOccHighLimit(1e-4), // high limit for accepting occupancy values + fQmaxLowLimit(8), // low limit for accepting Qmax values + fQmaxHighLimit(40) // high limit for accepting Qmax values { // ctor fTPCdataQA = new AliTPCdataQA*[AliRecoParam::kNSpecies] ; @@ -85,7 +90,11 @@ AliTPCQADataMakerRec::AliTPCQADataMakerRec() : //____________________________________________________________________________ AliTPCQADataMakerRec::AliTPCQADataMakerRec(const AliTPCQADataMakerRec& qadm) : AliQADataMakerRec(), - fTPCdataQA(NULL) + fTPCdataQA(NULL), + fBeautifyOption(qadm.GetBeautifyOption()), + fOccHighLimit(qadm.GetOccHighLimit()), + fQmaxLowLimit(qadm.GetQmaxLowLimit()), + fQmaxHighLimit(qadm.GetQmaxHighLimit()) { //copy ctor // Does not copy the calibration object, instead InitRaws have to be @@ -143,16 +152,20 @@ void AliTPCQADataMakerRec::EndOfDetectorCycle(AliQAv1::TASKINDEX_t task, TObjArr // RAW data files with no TPC data SetEventSpecie(AliRecoParam::ConvertIndex(specie)) ; - TH1F * histRawsOccupancy = (TH1F*)GetRawsData(kOccupancy) ; - TH1F * histRawsOccupancyVsSector = (TH1F*)GetRawsData(kOccupancyVsSector) ; - TH1F * histRawsNClustersPerEventVsSector = (TH1F*)GetRawsData(kNClustersPerEventVsSector) ; - TH1F * histRawsQVsSector = (TH1F*)GetRawsData(kQVsSector) ; - TH1F * histRawsQmaxVsSector = (TH1F*)GetRawsData(kQmaxVsSector) ; + TH1F * histRawsOccupancy = (TH1F*)GetRawsData(kRawsOccupancy) ; + TH1F * histRawsOccupancyVsSector = (TH1F*)GetRawsData(kRawsOccupancyVsSector) ; + TH1F * histRawsNClustersPerEventVsSector = (TH1F*)GetRawsData(kRawsNClustersPerEventVsSector) ; + TH1F * histRawsQVsSector = (TH1F*)GetRawsData(kRawsQVsSector) ; + TH1F * histRawsQmaxVsSector = (TH1F*)GetRawsData(kRawsQmaxVsSector) ; + TH1F * histRawsOccupancyVsEvent = (TH1F*)GetRawsData(kRawsOccupancyVsEvent) ; + TH1F * histRawsNclustersVsEvent = (TH1F*)GetRawsData(kRawsNclustersVsEvent) ; if ( !histRawsOccupancy || - !histRawsOccupancyVsSector || - !histRawsNClustersPerEventVsSector || - !histRawsQVsSector || - !histRawsQmaxVsSector) { + !histRawsOccupancyVsSector || + !histRawsNClustersPerEventVsSector || + !histRawsQVsSector || + !histRawsQmaxVsSector || + !histRawsOccupancyVsEvent || + !histRawsNclustersVsEvent ) { AliError("Something very wrong here, corrupted memory ?????. Please check\n") ; continue ; } @@ -171,12 +184,10 @@ void AliTPCQADataMakerRec::EndOfDetectorCycle(AliQAv1::TASKINDEX_t task, TObjArr histRawsQVsSector->Reset(); histRawsQmaxVsSector->Reset(); - TH1F* hNorm72 = new TH1F("hNorm72", "histogram to normalize 72 sectors", - 72, 0, 72); - hNorm72->Sumw2(); - TH1F* hNorm108 = new TH1F("hNorm108", "histogram to normalize 108 sectors (medium and long pads are split up)", - 108, 0, 108); - hNorm108->Sumw2(); + TH1F* hNormOcc = new TH1F("hNormOcc", 0, 72, 0, 72); + hNormOcc->Sumw2(); + TH1F* hNormNclusters = new TH1F("hNormNclusters", 0, 72, 0, 72); + hNormNclusters->Sumw2(); for (Int_t iSec = 0; iSec < 72; iSec++) { @@ -192,46 +203,131 @@ void AliTPCQADataMakerRec::EndOfDetectorCycle(AliQAv1::TASKINDEX_t task, TObjArr const Int_t nRows = occupancyROC->GetNrows(); for (Int_t iRow = 0; iRow < nRows; iRow++) { - Int_t helpSector = iSec; - if(iRow>=64) - helpSector += 36; // OROC (long pads) - const Int_t nPads = occupancyROC->GetNPads(iRow); for (Int_t iPad = 0; iPad < nPads; iPad++) { - + histRawsOccupancy->Fill(occupancyROC->GetValue(iRow, iPad)); - hNorm72->Fill(iSec); + hNormOcc->Fill(iSec); histRawsOccupancyVsSector - ->Fill(iSec, occupancyROC->GetValue(iRow, iPad)); - + ->Fill(iSec, occupancyROC->GetValue(iRow, iPad)); + const Int_t nClusters = TMath::Nint(nclusterROC->GetValue(iRow, iPad)); - - if(nClusters>0) { + if(nClusters>0) { + + hNormNclusters->Fill(iSec,nClusters); histRawsNClustersPerEventVsSector->Fill(iSec, nClusters); - hNorm108->Fill(helpSector, nClusters); - histRawsQVsSector->Fill(helpSector, - nClusters*qROC->GetValue(iRow, iPad)); - histRawsQmaxVsSector->Fill(helpSector, - nClusters*qmaxROC->GetValue(iRow, iPad)); + histRawsQVsSector->Fill(iSec, + nClusters*qROC->GetValue(iRow, iPad)); + histRawsQmaxVsSector->Fill(iSec, + nClusters*qmaxROC->GetValue(iRow, iPad)); } } } } // end loop over sectors + // update event histograms - copy info from TPDdataQA histos + TH1F* hQAOccVsEvent = fTPCdataQA[specie]->GetHistOccupancyVsEvent(); + TH1F* hQANclVsEvent = fTPCdataQA[specie]->GetHistNclustersVsEvent(); + + // the two event histograms should have the same number of bins + const Int_t nBins = hQAOccVsEvent->GetXaxis()->GetNbins(); + for(Int_t bin = 1; bin <= nBins; bin++) { + + histRawsOccupancyVsEvent->SetBinContent(bin, hQAOccVsEvent->GetBinContent(bin)); + histRawsNclustersVsEvent->SetBinContent(bin, hQANclVsEvent->GetBinContent(bin)); + } + + histRawsOccupancyVsEvent->GetXaxis()->SetRange(hQAOccVsEvent->GetXaxis()->GetFirst(), hQAOccVsEvent->GetXaxis()->GetLast()); + histRawsNclustersVsEvent->GetXaxis()->SetRange(hQANclVsEvent->GetXaxis()->GetFirst(), hQANclVsEvent->GetXaxis()->GetLast()); + // Normalize histograms - histRawsOccupancyVsSector->Divide(hNorm72); + histRawsOccupancyVsSector->Divide(hNormOcc); histRawsNClustersPerEventVsSector->Scale(1.0/Float_t(eventCounter)); - histRawsQVsSector->Divide(hNorm108); - histRawsQmaxVsSector->Divide(hNorm108); - delete hNorm72; - delete hNorm108; + histRawsQVsSector->Divide(hNormNclusters); + histRawsQmaxVsSector->Divide(hNormNclusters); + delete hNormOcc; + delete hNormNclusters; + + if(fBeautifyOption!=0) { + // Help make the histogram easier to interpret for the DQM shifter + + histRawsOccupancyVsSector->ResetBit(AliQAv1::GetQABit()); + histRawsQmaxVsSector->ResetBit(AliQAv1::GetQABit()); + + histRawsOccupancyVsSector->SetMinimum(0.0); + if(histRawsOccupancyVsSector->GetMaximum()<1.5*fOccHighLimit) + histRawsOccupancyVsSector->SetMaximum(1.5*fOccHighLimit); + + histRawsQmaxVsSector->SetMinimum(0.0); + if(histRawsQmaxVsSector->GetMaximum()<1.5*fQmaxHighLimit) + histRawsQmaxVsSector->SetMaximum(1.5*fQmaxHighLimit); + + Double_t xminOcc = histRawsOccupancyVsSector->GetXaxis()->GetXmin(); + Double_t xmaxOcc = histRawsOccupancyVsSector->GetXaxis()->GetXmax(); + Double_t yminOcc = histRawsOccupancyVsSector->GetMinimum(); + Double_t ymaxOcc = histRawsOccupancyVsSector->GetMaximum(); + + Double_t xminQmax = histRawsQmaxVsSector->GetXaxis()->GetXmin(); + Double_t xmaxQmax = histRawsQmaxVsSector->GetXaxis()->GetXmax(); + Double_t yminQmax = histRawsQmaxVsSector->GetMinimum(); + Double_t ymaxQmax = histRawsQmaxVsSector->GetMaximum(); + + TBox* boxOccOk = new TBox(xminOcc,0,xmaxOcc,fOccHighLimit); + boxOccOk->SetFillColor(kGreen); + histRawsOccupancyVsSector->GetListOfFunctions()->Add(boxOccOk); + + TBox* boxQmaxOk = new TBox(xminQmax,fQmaxLowLimit,xmaxQmax,fQmaxHighLimit); + boxQmaxOk->SetFillColor(kGreen); + histRawsQmaxVsSector->GetListOfFunctions()->Add(boxQmaxOk); + + + for(Int_t bin = 1; bin <= 72; bin++) { + + if(histRawsOccupancyVsSector->GetBinContent(bin)<=0 || + histRawsOccupancyVsSector->GetBinContent(bin)>fOccHighLimit) { + + histRawsOccupancyVsSector->SetBit(AliQAv1::GetQABit()); + + TBox* boxErr = + new TBox(histRawsOccupancyVsSector->GetXaxis()->GetBinLowEdge(bin), yminOcc, + histRawsOccupancyVsSector->GetXaxis()->GetBinUpEdge(bin), ymaxOcc); + boxErr->SetFillColor(kRed); + histRawsOccupancyVsSector->GetListOfFunctions()->Add(boxErr); + } + + if(histRawsQmaxVsSector->GetBinContent(bin)GetBinContent(bin)>fQmaxHighLimit) { + + // Mark that histogram has error + histRawsQmaxVsSector->SetBit(AliQAv1::GetQABit()); + + TBox* boxErr = + new TBox(histRawsQmaxVsSector->GetXaxis()->GetBinLowEdge(bin), yminQmax, + histRawsQmaxVsSector->GetXaxis()->GetBinUpEdge(bin), ymaxQmax); + boxErr->SetFillColor(kRed); + histRawsQmaxVsSector->GetListOfFunctions()->Add(boxErr); + } + } + + // Now we have to add a copy of the histograms to draw + // because the boxes covers the data points + TH1F* hOccCopy = new TH1F(*histRawsOccupancyVsSector); + hOccCopy->SetOption("SAME P"); + histRawsOccupancyVsSector->GetListOfFunctions()->Add(hOccCopy); + + TH1F* hQmaxCopy = new TH1F(*histRawsQmaxVsSector); + hQmaxCopy->SetOption("SAME P"); + histRawsQmaxVsSector->GetListOfFunctions()->Add(hQmaxCopy); + + } // end beautify } } } AliQAChecker::Instance()->Run(AliQAv1::kTPC, task, list) ; } + //____________________________________________________________________________ void AliTPCQADataMakerRec::InitESDs() { @@ -256,6 +352,9 @@ void AliTPCQADataMakerRec::InitESDs() 50, 0, 5); histESDpt->Sumw2(); Add2ESDsList(histESDpt, kPt, !expert, image); + + // This means we are not running DQM so do not beautify + SetBeautifyOption(0); } //____________________________________________________________________________ @@ -274,6 +373,11 @@ void AliTPCQADataMakerRec::InitRaws() const Bool_t image = kTRUE ; for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) { + + // It might happen that we will be in this method a few times because + // we create all dataQAs at the first call to this method + if(fTPCdataQA[specie]!=0) // data QA already created + continue; fTPCdataQA[specie] = new AliTPCdataQA(AliRecoParam::ConvertIndex(specie)); LoadMaps(); // Load Altro maps fTPCdataQA[specie]->SetAltroMapping(fMapping); // set Altro mapping @@ -285,31 +389,59 @@ void AliTPCQADataMakerRec::InitRaws() new TH1F("hRawsOccupancy", "Occupancy (all pads); Occupancy; Counts", 100, 0, 1); histRawsOccupancy->Sumw2(); - Add2RawsList(histRawsOccupancy, kOccupancy, !expert, image, !saveCorr); + Add2RawsList(histRawsOccupancy, kRawsOccupancy, expert, image, !saveCorr); TH1F * histRawsOccupancyVsSector = new TH1F("hRawsOccupancyVsSector", "Occupancy vs sector; Sector; Occupancy", 72, 0, 72); histRawsOccupancyVsSector->Sumw2(); - Add2RawsList(histRawsOccupancyVsSector, kOccupancyVsSector, !expert, image, !saveCorr); + histRawsOccupancyVsSector->SetMarkerStyle(20); + histRawsOccupancyVsSector->SetOption("P"); + histRawsOccupancyVsSector->SetStats(kFALSE); + Add2RawsList(histRawsOccupancyVsSector, kRawsOccupancyVsSector, !expert, image, !saveCorr); TH1F * histRawsNClustersPerEventVsSector = new TH1F("hRawsNClustersPerEventVsSector", "Nclusters per event vs sector; Sector; Nclusters per event", 72, 0, 72); histRawsNClustersPerEventVsSector->Sumw2(); - Add2RawsList(histRawsNClustersPerEventVsSector, kNClustersPerEventVsSector, !expert, image, !saveCorr); + Add2RawsList(histRawsNClustersPerEventVsSector, kRawsNClustersPerEventVsSector, expert, image, !saveCorr); TH1F * histRawsQVsSector = - new TH1F("hRawsQVsSector", " vs sector (OROC med: 36-71, long: 72-107); Sector; ", - 108, 0, 108); + new TH1F("hRawsQVsSector", " vs sector; Sector; ", + 72, 0, 72); histRawsQVsSector->Sumw2(); - Add2RawsList(histRawsQVsSector, kQVsSector, !expert, image, !saveCorr); + Add2RawsList(histRawsQVsSector, kRawsQVsSector, expert, image, !saveCorr); TH1F * histRawsQmaxVsSector = - new TH1F("hRawsQmaxVsSector", " vs sector (OROC med: 36-71, long: 72-107); Sector; ", - 108, 0, 108); + new TH1F("hRawsQmaxVsSector", " vs sector; Sector; ", + 72, 0, 72); histRawsQmaxVsSector->Sumw2(); - Add2RawsList(histRawsQmaxVsSector, kQmaxVsSector, !expert, image, !saveCorr); + histRawsQmaxVsSector->SetMarkerStyle(20); + histRawsQmaxVsSector->SetOption("P"); + histRawsQmaxVsSector->SetStats(kFALSE); + Add2RawsList(histRawsQmaxVsSector, kRawsQmaxVsSector, !expert, image, !saveCorr); + + // Get histogram information from data QA to build copy + TH1F* hOccHelp = fTPCdataQA[0]->GetHistOccupancyVsEvent(); + TH1F * histRawsOccupancyVsEvent = + new TH1F("hRawsOccupancyVsEvent", hOccHelp->GetTitle(), + hOccHelp->GetXaxis()->GetNbins(), + hOccHelp->GetXaxis()->GetXmin(), hOccHelp->GetXaxis()->GetXmax()); + histRawsOccupancyVsEvent->SetMarkerStyle(20); + histRawsOccupancyVsEvent->SetOption("P"); + histRawsOccupancyVsEvent->SetStats(kFALSE); + Add2RawsList(histRawsOccupancyVsEvent, kRawsOccupancyVsEvent, !expert, image, !saveCorr); + + // Get histogram information from data QA to build copy + TH1F* hNclHelp = fTPCdataQA[0]->GetHistNclustersVsEvent(); + TH1F * histRawsNclustersVsEvent = + new TH1F("hRawsNclustersVsEvent", hNclHelp->GetTitle(), + hNclHelp->GetXaxis()->GetNbins(), + hNclHelp->GetXaxis()->GetXmin(), hNclHelp->GetXaxis()->GetXmax()); + histRawsNclustersVsEvent->SetMarkerStyle(20); + histRawsNclustersVsEvent->SetOption("P"); + histRawsNclustersVsEvent->SetStats(kFALSE); + Add2RawsList(histRawsNclustersVsEvent, kRawsNclustersVsEvent, !expert, image, !saveCorr); } //____________________________________________________________________________ @@ -322,6 +454,9 @@ void AliTPCQADataMakerRec::InitDigits() 1000, 0, 1000); histDigitsADC->Sumw2(); Add2DigitsList(histDigitsADC, kDigitsADC, !expert, image); + + // This means we are not running DQM so do not beautify + SetBeautifyOption(0); } //____________________________________________________________________________ @@ -371,6 +506,9 @@ void AliTPCQADataMakerRec::InitRecPoints() 159, 0, 159); histRecPointsRow->Sumw2(); Add2RecPointsList(histRecPointsRow, kRow, !expert, image); + + // This means we are not running DQM so do not beautify + SetBeautifyOption(0); } //____________________________________________________________________________ @@ -496,6 +634,9 @@ void AliTPCQADataMakerRec::LoadMaps() path += "/TPC/mapping/Patch"; for(Int_t i = 0; i < 6; i++) { + + if(fMapping[i]!=0) // mapping already loaded + continue; TString path2 = path; path2 += i; path2 += ".data"; diff --git a/TPC/AliTPCQADataMakerRec.h b/TPC/AliTPCQADataMakerRec.h index 19b7f89f36f..1fe41e3c696 100644 --- a/TPC/AliTPCQADataMakerRec.h +++ b/TPC/AliTPCQADataMakerRec.h @@ -29,7 +29,7 @@ class AliTPCQADataMakerRec: public AliQADataMakerRec { public: - enum HRawsType_t {kTPCdataQA=0, kOccupancy, kOccupancyVsSector, kNClustersPerEventVsSector, kQVsSector, kQmaxVsSector} ; + enum HRawsType_t {kRawsOccupancy=0, kRawsOccupancyVsSector, kRawsNClustersPerEventVsSector, kRawsQVsSector, kRawsQmaxVsSector, kRawsOccupancyVsEvent, kRawsNclustersVsEvent} ; enum HDigitType_t {kDigitsADC=0} ; enum HRECPOINTsType_t {KClusters=0, kRatio, kPt} ; enum HESDsType_t {kQmaxShort=0, kQmaxMedium, kQmaxLong, kQShort, kQMedium, kQLong, kRow} ; @@ -39,6 +39,16 @@ public: AliTPCQADataMakerRec& operator = (const AliTPCQADataMakerRec& qadm) ; virtual ~AliTPCQADataMakerRec(); + void SetBeautifyOption(Int_t value) {fBeautifyOption= value;} + void SetOccHighLimit(Float_t value) {fOccHighLimit = value;} + void SetQmaxLowLimit(Float_t value) {fQmaxLowLimit = value;} + void SetQmaxHighLimit(Float_t value) {fQmaxHighLimit = value;} + + Int_t GetBeautifyOption() const {return fBeautifyOption;} + Float_t GetOccHighLimit() const {return fOccHighLimit; } + Float_t GetQmaxLowLimit() const {return fQmaxLowLimit; } + Float_t GetQmaxHighLimit() const {return fQmaxHighLimit;} + private: virtual void StartOfDetectorCycle() {}; // empty virtual void EndOfDetectorCycle(AliQAv1::TASKINDEX_t, TObjArray** list) ; @@ -62,10 +72,14 @@ private: virtual void LoadMaps(); - AliTPCAltroMapping *fMapping[6]; //! Pointers to ALTRO mapping AliTPCdataQA** fTPCdataQA;//! TPC calibration object for making raw data QA + Int_t fBeautifyOption;//! 0:no beautify, !=0:beautify RAW + Float_t fOccHighLimit; //! high limit for accepting occupancy values + Float_t fQmaxLowLimit; //! low limit for accepting Qmax values + Float_t fQmaxHighLimit; //! high limit for accepting Qmax values + ClassDef(AliTPCQADataMakerRec,1) // TPC Rec Quality Assurance Data Maker }; diff --git a/TPC/AliTPCdataQA.cxx b/TPC/AliTPCdataQA.cxx index bfaf56c66a5..8322f33561c 100644 --- a/TPC/AliTPCdataQA.cxx +++ b/TPC/AliTPCdataQA.cxx @@ -91,6 +91,7 @@ using namespace std; //header file #include "AliTPCdataQA.h" +#include "AliLog.h" ClassImp(AliTPCdataQA) @@ -116,8 +117,14 @@ AliTPCdataQA::AliTPCdataQA() : /*FOLD00*/ fHistQVsTimeSideC(0), fHistQMaxVsTimeSideA(0), fHistQMaxVsTimeSideC(0), + fHistOccupancyVsEvent(0), + fHistNclustersVsEvent(0), fEventCounter(0), fIsAnalysed(kFALSE), + fMaxEvents(500000), // Max events for event histograms + fEventsPerBin(1000), // Events per bin for event histograms + fSignalCounter(0), // Signal counter + fClusterCounter(0), // Cluster counter fAllBins(0), fAllSigBins(0), fAllNSigBins(0), @@ -153,8 +160,14 @@ fHistQVsTimeSideA(0), fHistQVsTimeSideC(0), fHistQMaxVsTimeSideA(0), fHistQMaxVsTimeSideC(0), +fHistOccupancyVsEvent(0), +fHistNclustersVsEvent(0), fEventCounter(0), fIsAnalysed(kFALSE), +fMaxEvents(500000), +fEventsPerBin(1000), +fSignalCounter(0), +fClusterCounter(0), fAllBins(0), fAllSigBins(0), fAllNSigBins(0), @@ -191,8 +204,14 @@ AliTPCdataQA::AliTPCdataQA(const AliTPCdataQA &ped) : /*FOLD00*/ fHistQVsTimeSideC(0), fHistQMaxVsTimeSideA(0), fHistQMaxVsTimeSideC(0), + fHistOccupancyVsEvent(0), + fHistNclustersVsEvent(0), fEventCounter(ped.GetEventCounter()), fIsAnalysed(ped.GetIsAnalysed()), + fMaxEvents(ped.GetMaxEvents()), + fEventsPerBin(ped.GetEventsPerBin()), + fSignalCounter(ped.GetSignalCounter()), + fClusterCounter(ped.GetClusterCounter()), fAllBins(0), fAllSigBins(0), fAllNSigBins(0), @@ -239,6 +258,14 @@ AliTPCdataQA::AliTPCdataQA(const AliTPCdataQA &ped) : /*FOLD00*/ fHistQMaxVsTimeSideC = new TProfile(*ped.GetHistQMaxVsTimeSideC()); fHistQMaxVsTimeSideC->SetDirectory(0); } + if(ped.GetHistOccupancyVsEventConst()) { + fHistOccupancyVsEvent = new TH1F(*ped.GetHistOccupancyVsEventConst()); + fHistOccupancyVsEvent->SetDirectory(0); + } + if(ped.GetHistNclustersVsEventConst()) { + fHistNclustersVsEvent = new TH1F(*ped.GetHistNclustersVsEventConst()); + fHistNclustersVsEvent->SetDirectory(0); + } } //_____________________________________________________________________ @@ -265,8 +292,14 @@ AliTPCdataQA::AliTPCdataQA(const TMap *config) : /*FOLD00*/ fHistQVsTimeSideC(0), fHistQMaxVsTimeSideA(0), fHistQMaxVsTimeSideC(0), + fHistOccupancyVsEvent(0), + fHistNclustersVsEvent(0), fEventCounter(0), fIsAnalysed(kFALSE), + fMaxEvents(500000), + fEventsPerBin(1000), + fSignalCounter(0), + fClusterCounter(0), fAllBins(0), fAllSigBins(0), fAllNSigBins(0), @@ -281,6 +314,8 @@ AliTPCdataQA::AliTPCdataQA(const TMap *config) : /*FOLD00*/ if (config->GetValue("LastTimeBin")) fLastTimeBin = ((TObjString*)config->GetValue("LastTimeBin"))->GetString().Atoi(); if (config->GetValue("AdcMin")) fAdcMin = ((TObjString*)config->GetValue("AdcMin"))->GetString().Atoi(); if (config->GetValue("AdcMax")) fAdcMax = ((TObjString*)config->GetValue("AdcMax"))->GetString().Atoi(); + if (config->GetValue("MaxEvents")) fMaxEvents = ((TObjString*)config->GetValue("MaxEvents"))->GetString().Atoi(); + if (config->GetValue("EventsPerBin")) fAdcMax = ((TObjString*)config->GetValue("EventsPerBin"))->GetString().Atoi(); } //_____________________________________________________________________ @@ -321,6 +356,8 @@ AliTPCdataQA::~AliTPCdataQA() /*FOLD00*/ delete fHistQVsTimeSideC; delete fHistQMaxVsTimeSideA; delete fHistQMaxVsTimeSideC; + delete fHistOccupancyVsEvent; + delete fHistNclustersVsEvent; for (Int_t iRow = 0; iRow < fRowsMax; iRow++) { delete [] fAllBins[iRow]; @@ -330,6 +367,95 @@ AliTPCdataQA::~AliTPCdataQA() /*FOLD00*/ delete [] fAllSigBins; delete [] fAllNSigBins; } + +//_____________________________________________________________________ +TH1F* AliTPCdataQA::GetHistOccupancyVsEvent() +{ + // + // Create Occupancy vs event histogram + // (we create this histogram differently then the other histograms + // because this we want to be able to access and copy + // from AliTPCQAMakerRec before it normally would be created) + // + if(!fHistOccupancyVsEvent) { + + Int_t nBins = fMaxEvents/fEventsPerBin; + fHistOccupancyVsEvent = new TH1F("hOccupancyVsEvent", "Occupancy vs event number (~time); Event number; Occupancy", nBins, 0, nBins*fEventsPerBin); + fHistOccupancyVsEvent->SetDirectory(0); + fHistOccupancyVsEvent->GetXaxis()->SetRange(0, 10); + } + + return fHistOccupancyVsEvent; +} + +//_____________________________________________________________________ +TH1F* AliTPCdataQA::GetHistNclustersVsEvent() +{ + // + // Create Nclusters vs event histogram + // (we create this histogram differently then the other histograms + // because this we want to be able to access and copy + // from AliTPCQAMakerRec before it normally would be created) + // + if(!fHistNclustersVsEvent) { + + Int_t nBins = fMaxEvents/fEventsPerBin; + fHistNclustersVsEvent = new TH1F("hNclustersVsEvent", "Nclusters vs event number (~time); Event number; Nclusters per event", nBins, 0, nBins*fEventsPerBin); + fHistNclustersVsEvent->SetDirectory(0); + fHistNclustersVsEvent->GetXaxis()->SetRange(0, 10); + } + + return fHistNclustersVsEvent; +} + +//_____________________________________________________________________ +void AliTPCdataQA::UpdateEventHistograms() +{ + // Update histograms that display occupancy and + // number of clusters as a function of number of + // events + if (!fHistOccupancyVsEvent) + GetHistOccupancyVsEvent(); + if (!fHistNclustersVsEvent) + GetHistNclustersVsEvent(); + + Float_t averageOccupancy = + Float_t(fSignalCounter)/fEventsPerBin/(fLastTimeBin - fFirstTimeBin +1.0) + / 570132; // 570,132 is number of pads + if(fEventCounter<=fMaxEvents) + UpdateEventHisto(fHistOccupancyVsEvent, averageOccupancy); + fSignalCounter = 0; + + Float_t averageNclusters = + Float_t(fClusterCounter)/fEventsPerBin; + if(fEventCounter<=fMaxEvents) + UpdateEventHisto(fHistNclustersVsEvent, averageNclusters); + fClusterCounter = 0; +} + +//_____________________________________________________________________ +void AliTPCdataQA::UpdateEventHisto(TH1F* hist, Float_t average) +{ + // Do the actually updating of each histogram and + // change the visible range if needed + + // in case someone would have overwritten the value here + // (not so pretty but OK for this I think) + fEventsPerBin = hist->GetXaxis()->GetBinWidth(1); + Int_t bin = TMath::Nint(Float_t(fEventCounter)/fEventsPerBin); + + if (hist->GetBinContent(bin)>0) { + AliError("Bin already filled. This should not happen."); + } else { + hist->SetBinContent(bin, average); + } + + // expand the visible range of the histogram if needed + if(hist->GetXaxis()->GetLast()<= bin) { + hist->GetXaxis()->SetRange(0, Int_t(1.3*bin)); + } +} + //_____________________________________________________________________ Bool_t AliTPCdataQA::ProcessEvent(AliTPCRawStreamV3 *rawStreamV3) { @@ -385,8 +511,12 @@ Bool_t AliTPCdataQA::ProcessEvent(AliRawReader *rawReader) // AliTPCRawStreamV3 rawStreamV3(rawReader, (AliAltroMapping**)fMapping); Bool_t res=ProcessEvent(&rawStreamV3); - if(res) + if(res) { fEventCounter++; // only increment event counter if there is TPC data + + if(fEventCounter%fEventsPerBin==0) + UpdateEventHistograms(); + } return res; } @@ -657,6 +787,8 @@ Int_t AliTPCdataQA::Update(const Int_t iSector, /*FOLD00*/ // SetExpandDigit(iRow, iPad, iTimeBin, signal); + + fSignalCounter++; return 1; // signal was accepted } @@ -806,6 +938,7 @@ void AliTPCdataQA::FindLocalMaxima(const Int_t iSector) } // end loop over rows // cout << "Number of local maximas found: " << nLocalMaxima << endl; + fClusterCounter += nLocalMaxima; } //_____________________________________________________________________ diff --git a/TPC/AliTPCdataQA.h b/TPC/AliTPCdataQA.h index 565bb686353..41eda827221 100644 --- a/TPC/AliTPCdataQA.h +++ b/TPC/AliTPCdataQA.h @@ -66,6 +66,10 @@ public: TProfile* GetHistQVsTimeSideC() const {return fHistQVsTimeSideC;} TProfile* GetHistQMaxVsTimeSideA() const {return fHistQMaxVsTimeSideA;} TProfile* GetHistQMaxVsTimeSideC() const {return fHistQMaxVsTimeSideC;} + TH1F* GetHistOccupancyVsEventConst() const {return fHistOccupancyVsEvent;} + TH1F* GetHistNclustersVsEventConst() const {return fHistNclustersVsEvent;} + TH1F* GetHistOccupancyVsEvent(); + TH1F* GetHistNclustersVsEvent(); // AliTPCAltroMapping **GetAltroMapping() { return fMapping; }; @@ -78,10 +82,15 @@ public: Int_t GetAdcMax() const { return fAdcMax; } Int_t GetEventCounter() const { return fEventCounter; } Bool_t GetIsAnalysed() const { return fIsAnalysed; } + Int_t GetMaxEvents() const { return fMaxEvents; } + Int_t GetEventsPerBin() const { return fEventsPerBin; } + Int_t GetSignalCounter() const { return fSignalCounter; } + Int_t GetClusterCounter() const { return fClusterCounter;} + void SetRangeTime(Int_t tMin, Int_t tMax){ fFirstTimeBin=tMin; fLastTimeBin=tMax;} // Set time bin range that is used for the pedestal calibration void SetRangeAdc (Int_t aMin, Int_t aMax){ fAdcMin=aMin; fAdcMax=aMax; } // Set adc range for the pedestal calibration - - + void SetMaxEvents (Int_t value) { fMaxEvents = value; } + void SetEventsPerBin(Int_t value) { fEventsPerBin = value; } private: Int_t Update(const Int_t iSector, const Int_t iRow, const Int_t iPad, @@ -96,6 +105,8 @@ private: Float_t GetQ(const Float_t* adcArray, const Int_t time, const Int_t pad, const Int_t maxTimeBins, Int_t& timeMin,Int_t& timeMax,Int_t& padMin,Int_t& padMax); + void UpdateEventHistograms(); + void UpdateEventHisto(TH1F* hist, Float_t average); Int_t fFirstTimeBin; // First Time bin needed for analysis Int_t fLastTimeBin; // Last Time bin needed for analysis @@ -123,8 +134,16 @@ private: TProfile* fHistQMaxVsTimeSideA; // QMax vs time (side A) TProfile* fHistQMaxVsTimeSideC; // QMax vs time (side C) + TH1F* fHistOccupancyVsEvent; // Occupancy vs event number (~time) + TH1F* fHistNclustersVsEvent; // Nclusters vs event number (~time) + Int_t fEventCounter; // event Counter Bool_t fIsAnalysed; // Set to true after Analyse has been called + + Int_t fMaxEvents; // Max events for event histograms + Int_t fEventsPerBin; // Events per bin for event histograms + Int_t fSignalCounter; // Signal counter + Int_t fClusterCounter; // Cluster counter // // Expand buffer // @@ -137,7 +156,7 @@ private: public: - ClassDef(AliTPCdataQA, 4) // Implementation of the TPC pedestal and noise calibration + ClassDef(AliTPCdataQA, 5) // Implementation of the TPC Raw QA }; -- 2.39.3