diff --git a/Modules/MUON/MCH/CMakeLists.txt b/Modules/MUON/MCH/CMakeLists.txt index 060d71e303..b4068b84e6 100644 --- a/Modules/MUON/MCH/CMakeLists.txt +++ b/Modules/MUON/MCH/CMakeLists.txt @@ -10,6 +10,8 @@ set(SRCS src/DecodingErrorsTask.cxx src/PedestalsCheck.cxx src/PhysicsCheck.cxx + src/PhysicsOccupancyCheck.cxx + src/PhysicsPreclustersCheck.cxx src/TH1MCHReductor.cxx ) @@ -21,8 +23,15 @@ set(HEADERS include/MCH/DecodingErrorsTask.h include/MCH/PedestalsCheck.h include/MCH/PhysicsCheck.h + include/MCH/PhysicsOccupancyCheck.h + include/MCH/PhysicsPreclustersCheck.h include/MCH/TH1MCHReductor.h include/MCH/MergeableTH2Ratio.h + include/MCH/MergeableTH1OccupancyPerDE.h + include/MCH/MergeableTH1OccupancyPerDECycle.h + include/MCH/MergeableTH1PseudoEfficiencyPerDE.h + include/MCH/MergeableTH1PseudoEfficiencyPerDECycle.h + include/MCH/MergeableTH1MPVPerDECycle.h ) # ---- Library ---- @@ -67,11 +76,18 @@ add_root_dictionary(${MODULE_NAME} include/MCH/PhysicsTaskDigits.h include/MCH/PhysicsTaskPreclusters.h include/MCH/PhysicsCheck.h + include/MCH/PhysicsOccupancyCheck.h + include/MCH/PhysicsPreclustersCheck.h include/MCH/DecodingErrorsTask.h include/MCH/PedestalsCheck.h include/MCH/TH1MCHReductor.h include/MCH/sampa_header.h include/MCH/MergeableTH2Ratio.h + include/MCH/MergeableTH1OccupancyPerDE.h + include/MCH/MergeableTH1OccupancyPerDECycle.h + include/MCH/MergeableTH1PseudoEfficiencyPerDE.h + include/MCH/MergeableTH1PseudoEfficiencyPerDECycle.h + include/MCH/MergeableTH1MPVPerDECycle.h LINKDEF include/MCH/LinkDef.h) # ---- Tests ---- diff --git a/Modules/MUON/MCH/include/MCH/GlobalHistogram.h b/Modules/MUON/MCH/include/MCH/GlobalHistogram.h index fa45815f0a..08a1d63f4c 100644 --- a/Modules/MUON/MCH/include/MCH/GlobalHistogram.h +++ b/Modules/MUON/MCH/include/MCH/GlobalHistogram.h @@ -29,9 +29,25 @@ namespace quality_control_modules namespace muonchambers { +std::string getHistoPath(int deId); + +class DetectorHistogram : public TH2F +{ + public: + DetectorHistogram(TString name, TString title, int deId); + + void Fill(double padX, double padY, double padSizeX, double padSizeY, double val = 1); + void Set(double padX, double padY, double padSizeX, double padSizeY, double val); + + private: + int mDeId{ 0 }; + + bool mFlipX{ false }; + bool mFlipY{ false }; +}; + class GlobalHistogram : public TH2F { - int getLR(int de); void getDeCenter(int de, float& xB0, float& yB0, float& xNB0, float& yNB0); void getDeCenterST3(int de, float& xB0, float& yB0, float& xNB0, float& yNB0); void getDeCenterST4(int de, float& xB0, float& yB0, float& xNB0, float& yNB0); @@ -43,13 +59,13 @@ class GlobalHistogram : public TH2F void init(); // add the histograms of the individual detection elements - void add(std::map& histB, std::map& histNB); + void add(std::map& histB, std::map& histNB); // replace the contents with the histograms of the individual detection elements, including null bins - void set_includeNull(std::map& histB, std::map& histNB); + void set_includeNull(std::map& histB, std::map& histNB); // replace the contents with the histograms of the individual detection elements - void set(std::map& histB, std::map& histNB, bool doAverage = true, bool includeNullBins = false); + void set(std::map& histB, std::map& histNB, bool doAverage = true, bool includeNullBins = false); }; } // namespace muonchambers diff --git a/Modules/MUON/MCH/include/MCH/LinkDef.h b/Modules/MUON/MCH/include/MCH/LinkDef.h index 72596d9a99..776b01d834 100644 --- a/Modules/MUON/MCH/include/MCH/LinkDef.h +++ b/Modules/MUON/MCH/include/MCH/LinkDef.h @@ -9,7 +9,14 @@ #pragma link C++ class o2::quality_control_modules::muonchambers::DecodingErrorsTask + ; #pragma link C++ class o2::quality_control_modules::muonchambers::PedestalsCheck + ; #pragma link C++ class o2::quality_control_modules::muonchambers::PhysicsCheck + ; +#pragma link C++ class o2::quality_control_modules::muonchambers::PhysicsOccupancyCheck + ; +#pragma link C++ class o2::quality_control_modules::muonchambers::PhysicsPreclustersCheck + ; #pragma link C++ class o2::quality_control_modules::muonchambers::TH1MCHReductor + ; #pragma link C++ class o2::quality_control_modules::muonchambers::MergeableTH2Ratio + ; +#pragma link C++ class o2::quality_control_modules::muonchambers::MergeableTH1OccupancyPerDE + ; +#pragma link C++ class o2::quality_control_modules::muonchambers::MergeableTH1OccupancyPerDECycle + ; +#pragma link C++ class o2::quality_control_modules::muonchambers::MergeableTH1PseudoEfficiencyPerDE + ; +#pragma link C++ class o2::quality_control_modules::muonchambers::MergeableTH1PseudoEfficiencyPerDECycle + ; +#pragma link C++ class o2::quality_control_modules::muonchambers::MergeableTH1MPVPerDECycle + ; #endif diff --git a/Modules/MUON/MCH/include/MCH/MergeableGlobalHistogramRatio.h b/Modules/MUON/MCH/include/MCH/MergeableGlobalHistogramRatio.h new file mode 100644 index 0000000000..5b247cae6f --- /dev/null +++ b/Modules/MUON/MCH/include/MCH/MergeableGlobalHistogramRatio.h @@ -0,0 +1,106 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MergeableGlobalHistogramRatio.h +/// \brief An example of a custom class inheriting MergeInterface +/// +/// \author Piotr Konopka, piotr.jan.konopka@cern.ch, Sebastien Perrin + +#ifndef O2_MERGEABLEGLOBALHISTOGRAMRATIO_H +#define O2_MERGEABLEGLOBALHISTOGRAMRATIO_H + +#include +#include +#include +#include +#include +#include "Mergers/MergeInterface.h" +#include "MCH/GlobalHistogram.h" + +using namespace std; +namespace o2::quality_control_modules::muonchambers +{ + +class MergeableGlobalHistogramRatio : public GlobalHistogram, public o2::mergers::MergeInterface +{ + public: + MergeableGlobalHistogramRatio() = default; + + MergeableGlobalHistogramRatio(MergeableGlobalHistogramRatio const& copymerge) + : GlobalHistogram(copymerge.getName(), copymerge.getTitle()), o2::mergers::MergeInterface(), mhistoNum(copymerge.getNum()), mhistoDen(copymerge.getDen()), mname(copymerge.getName()), mtitle(copymerge.getTitle()) + { + update(); + } + + MergeableGlobalHistogramRatio(const char* name, const char* title, GlobalHistogram* histonum, GlobalHistogram* histoden) + : GlobalHistogram(name, title), o2::mergers::MergeInterface(), mhistoNum(histonum), mhistoDen(histoden), mname(name), mtitle(title) + { + update(); + } + + ~MergeableGlobalHistogramRatio() override = default; + + void merge(MergeInterface* const other) override + { + mhistoNum->Add(dynamic_cast(other)->getNum()); + mhistoDen->Add(dynamic_cast(other)->getDen()); + update(); + } + + GlobalHistogram* getNum() const + { + return mhistoNum; + } + + GlobalHistogram* getDen() const + { + return mhistoDen; + } + + const char* getName() const + { + return mname; + } + + const char* getTitle() const + { + return mtitle; + } + + void update() + { + std::cout << "A1" << endl; + Reset("MICES"); + std::cout << "A2" << endl; + init(); + std::cout << "A3" << endl; + Divide(mhistoNum, mhistoDen); + std::cout << "A4" << endl; + // SetName(mname); + // SetTitle(mtitle); + std::cout << "A5" << endl; + Scale(1 / 87.5); + SetOption("colz"); + std::cout << "A6" << endl; + } + + private: + GlobalHistogram* mhistoNum{ nullptr }; + GlobalHistogram* mhistoDen{ nullptr }; + std::string mTreatMeAs = "TH2F"; + const char* mname = "DefaultName"; + const char* mtitle = "DefaultTitle"; + + ClassDefOverride(MergeableGlobalHistogramRatio, 1); +}; + +} // namespace o2::quality_control_modules::muonchambers + +#endif //O2_MERGEABLEGLOBALHISTOGRAMRATIO_H diff --git a/Modules/MUON/MCH/include/MCH/MergeableTH1MPVPerDECycle.h b/Modules/MUON/MCH/include/MCH/MergeableTH1MPVPerDECycle.h new file mode 100644 index 0000000000..6b2128c74e --- /dev/null +++ b/Modules/MUON/MCH/include/MCH/MergeableTH1MPVPerDECycle.h @@ -0,0 +1,126 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MergeableTH1OccupancyPerDE.h +/// \brief An example of a custom TH2Quotient inheriting MergeInterface +/// +/// \author Piotr Konopka, piotr.jan.konopka@cern.ch, Sebastien Perrin + +#ifndef O2_MERGEABLETH1MPVPERDECYCLE_H +#define O2_MERGEABLETH1MPVPERDECYCLE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Mergers/MergeInterface.h" +#include "MCHRawElecMap/Mapper.h" +#ifdef HAVE_DIGIT_IN_DATAFORMATS +#include "DataFormatsMCH/Digit.h" +#else +#include "MCHBase/Digit.h" +#endif + +using namespace std; +namespace o2::quality_control_modules::muonchambers +{ + +class MergeableTH1MPVPerDECycle : public TH1F, public o2::mergers::MergeInterface +{ + public: + MergeableTH1MPVPerDECycle() = default; + + MergeableTH1MPVPerDECycle(MergeableTH1MPVPerDECycle const& copymerge) + : TH1F("DefaultNameCycle", "DefaultTitleCycle", 1100, -0.5, 1099.5), o2::mergers::MergeInterface(), mhistosCharge(copymerge.getNum()) + { + } + + MergeableTH1MPVPerDECycle(const char* name, const char* title, std::map histosnum) + : TH1F(name, title, 1100, -0.5, 1099.5), o2::mergers::MergeInterface(), mhistosCharge(histosnum) + { + update(); + } + + ~MergeableTH1MPVPerDECycle() override = default; + + void merge(MergeInterface* const other) override + { //FIXME + for (auto de : o2::mch::raw::deIdsForAllMCH) { + auto hnum = dynamic_cast(other)->getNum().find(de); + if ((hnum != dynamic_cast(other)->getNum().end()) && (hnum->second != NULL)) { + + auto hnumfinal = mhistosCharge.find(de); + if ((hnumfinal != mhistosCharge.end()) && (hnumfinal->second != NULL)) { + hnumfinal->second->Add(hnum->second); + } + } + } + + update(); + } + + std::map getNum() const + { + return mhistosCharge; + } + + void update() + { //FIXME + const char* name = this->GetName(); + const char* title = this->GetTitle(); + Reset(); + SetNameTitle(name, title); + + TF1* f1 = new TF1("f1", "landau", 200, 5000); //1650V [200,5k] 1700V [400,10k] + + for (auto de : o2::mch::raw::deIdsForAllMCH) { + auto hLandauCycle = mhistosCharge.find(de); + if ((hLandauCycle != mhistosCharge.end()) && (hLandauCycle->second != NULL)) { + + double chindf = 0; + double mpv = 0; + + if (hLandauCycle->second->GetEntries() > 0) { + f1->SetParameter(1, 0); + f1->SetParameter(2, 500); // Start Sigma at 500 + // f1->FixParameter(1,1000); // Fix MPV 1650V 500 1700V 1000 + f1->SetParLimits(2, 100, 10000); + f1->SetParLimits(1, 0, 10000); + f1->SetParLimits(0, 0, 100000); // Say we want a positive Normalisation + TFitResultPtr ptr = hLandauCycle->second->Fit("f1", "RB"); + chindf = f1->GetChisquare() / f1->GetNDF(); + mpv = f1->GetParameter(1); + if (mpv > 0) { + cout << "DE : " << de << endl; + cout << "Chi2/ndf :" << chindf << endl; + cout << "MPV :" << mpv << endl; + } + } + + SetBinContent(de + 1, mpv); + } + } + } + + private: + std::map mhistosCharge; + std::string mTreatMeAs = "TH1F"; + + ClassDefOverride(MergeableTH1MPVPerDECycle, 1); +}; + +} // namespace o2::quality_control_modules::muonchambers + +#endif //O2_MERGEABLETH1MPVPERDECYCLE_H diff --git a/Modules/MUON/MCH/include/MCH/MergeableTH1OccupancyPerDE.h b/Modules/MUON/MCH/include/MCH/MergeableTH1OccupancyPerDE.h new file mode 100644 index 0000000000..29a722aa21 --- /dev/null +++ b/Modules/MUON/MCH/include/MCH/MergeableTH1OccupancyPerDE.h @@ -0,0 +1,160 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MergeableTH1OccupancyPerDE.h +/// \brief An example of a custom TH2Quotient inheriting MergeInterface +/// +/// \author Piotr Konopka, piotr.jan.konopka@cern.ch, Sebastien Perrin + +#ifndef O2_MERGEABLETH1OCCUPANCYPERDE_H +#define O2_MERGEABLETH1OCCUPANCYPERDE_H + +#include +#include +#include +#include +#include +#include +#include + +#include "Mergers/MergeInterface.h" +#include "MCHRawElecMap/Mapper.h" +#ifdef HAVE_DIGIT_IN_DATAFORMATS +#include "DataFormatsMCH/Digit.h" +#else +#include "MCHBase/Digit.h" +#endif +#ifdef MCH_HAS_MAPPING_FACTORY +#include "MCHMappingFactory/CreateSegmentation.h" +#endif +#include "MCHMappingInterface/Segmentation.h" +#include "MCHMappingInterface/CathodeSegmentation.h" +#include "MCHMappingSegContour/CathodeSegmentationContours.h" + +using namespace std; +namespace o2::quality_control_modules::muonchambers +{ + +class MergeableTH1OccupancyPerDE : public TH1F, public o2::mergers::MergeInterface +{ + public: + MergeableTH1OccupancyPerDE() = default; + + MergeableTH1OccupancyPerDE(MergeableTH1OccupancyPerDE const& copymerge) + : TH1F("DefaultName", "DefaultTitle", 1100, -0.5, 1099.5), o2::mergers::MergeInterface(), mhistoNum(copymerge.getNum()), mhistoDen(copymerge.getDen()) + { + } + + MergeableTH1OccupancyPerDE(const char* name, const char* title, TH2F* histonum, TH2F* histoden) + : TH1F(name, title, 1100, -0.5, 1099.5), o2::mergers::MergeInterface(), mhistoNum(histonum), mhistoDen(histoden) + { + update(); + } + + ~MergeableTH1OccupancyPerDE() override = default; + + void merge(MergeInterface* const other) override + { + mhistoNum->Add(dynamic_cast(other)->getNum()); + mhistoDen->Add(dynamic_cast(other)->getDen()); + + update(); + } + + TH2F* getNum() const + { + return mhistoNum; + } + + TH2F* getDen() const + { + return mhistoDen; + } + + void update() + { + mhistoDivTemp = new TH2F("TempNameDiv", "TempTitleDiv", mhistoNum->GetNbinsX(), 0, mhistoNum->GetNbinsX(), mhistoNum->GetNbinsY(), 0, mhistoNum->GetNbinsY()); + mhistoDivTemp->Divide(mhistoNum, mhistoDen); + + const char* name = this->GetName(); + const char* title = this->GetTitle(); + Reset(); + SetNameTitle(name, title); + + o2::mch::raw::Elec2DetMapper mElec2DetMapper = o2::mch::raw::createElec2DetMapper(); + o2::mch::raw::Det2ElecMapper mDet2ElecMapper = o2::mch::raw::createDet2ElecMapper(); + o2::mch::raw::FeeLink2SolarMapper mFeeLink2SolarMapper = o2::mch::raw::createFeeLink2SolarMapper(); + o2::mch::raw::Solar2FeeLinkMapper mSolar2FeeLinkMapper = o2::mch::raw::createSolar2FeeLinkMapper(); + + // Using OccupancyElec to get the mean occupancy per DE + // By looking at each bin in NHits Elec histogram, getting the Elec info (fee, link, de) for each bin, computing the number of hits seen on a given DE and dividing by the number of bins + double MeanOccupancyDE[1100]; + int NbinsDE[1100]; + auto h = mhistoDivTemp; + auto horbits = mhistoDen; + if (h && horbits) { + for (auto de : o2::mch::raw::deIdsForAllMCH) { + MeanOccupancyDE[de] = 0; + NbinsDE[de] = 0; + } + for (int binx = 1; binx < h->GetXaxis()->GetNbins() + 1; binx++) { + for (int biny = 1; biny < h->GetYaxis()->GetNbins() + 1; biny++) { + + int mNOrbits = horbits->GetBinContent(binx, biny); + if (mNOrbits <= 0) { + // no orbits detected for this channel, skip it + continue; + } + // Getting Elec information based on the definition of x and y bins in ElecHistograms + uint32_t dsAddr = (binx - 1) % 40; + uint32_t linkId = ((binx - 1 - dsAddr) / 40) % 12; + uint32_t feeId = (binx - 1 - dsAddr - 40 * linkId) / (12 * 40); + uint32_t de; + std::optional solarId = mFeeLink2SolarMapper(o2::mch::raw::FeeLinkId{ static_cast(feeId), static_cast(linkId) }); + if (!solarId.has_value()) { + continue; + } + std::optional dsDetId = + mElec2DetMapper(o2::mch::raw::DsElecId{ solarId.value(), static_cast(dsAddr / 5), static_cast(dsAddr % 5) }); + if (!dsDetId.has_value()) { + continue; + } + de = dsDetId->deId(); + + MeanOccupancyDE[de] += h->GetBinContent(binx, biny); + NbinsDE[de] += 1; + } + } + + for (auto i : o2::mch::raw::deIdsForAllMCH) { + if (NbinsDE[i] > 0) { + MeanOccupancyDE[i] /= NbinsDE[i]; + } + SetBinContent(i + 1, MeanOccupancyDE[i]); + } + } + + Scale(1 / 87.5); + + delete mhistoDivTemp; + } + + private: + TH2F* mhistoNum{ nullptr }; + TH2F* mhistoDen{ nullptr }; + TH2F* mhistoDivTemp{ nullptr }; + std::string mTreatMeAs = "TH1F"; + + ClassDefOverride(MergeableTH1OccupancyPerDE, 1); +}; + +} // namespace o2::quality_control_modules::muonchambers + +#endif //O2_MERGEABLETH1OCCUPANCYPERDE_H diff --git a/Modules/MUON/MCH/include/MCH/MergeableTH1OccupancyPerDECycle.h b/Modules/MUON/MCH/include/MCH/MergeableTH1OccupancyPerDECycle.h new file mode 100644 index 0000000000..f3c4a44d10 --- /dev/null +++ b/Modules/MUON/MCH/include/MCH/MergeableTH1OccupancyPerDECycle.h @@ -0,0 +1,222 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MergeableTH1OccupancyPerDE.h +/// \brief An example of a custom TH2Quotient inheriting MergeInterface +/// +/// \author Piotr Konopka, piotr.jan.konopka@cern.ch, Sebastien Perrin + +#ifndef O2_MERGEABLETH1OCCUPANCYPERDECYCLE_H +#define O2_MERGEABLETH1OCCUPANCYPERDECYCLE_H + +#include +#include +#include +#include +#include +#include +#include + +#include "Mergers/MergeInterface.h" +#include "MCHRawElecMap/Mapper.h" +#ifdef HAVE_DIGIT_IN_DATAFORMATS +#include "DataFormatsMCH/Digit.h" +#else +#include "MCHBase/Digit.h" +#endif +#ifdef MCH_HAS_MAPPING_FACTORY +#include "MCHMappingFactory/CreateSegmentation.h" +#endif +#include "MCHMappingInterface/Segmentation.h" +#include "MCHMappingInterface/CathodeSegmentation.h" +#include "MCHMappingSegContour/CathodeSegmentationContours.h" + +using namespace std; +namespace o2::quality_control_modules::muonchambers +{ + +class MergeableTH1OccupancyPerDECycle : public TH1F, public o2::mergers::MergeInterface +{ + public: + MergeableTH1OccupancyPerDECycle() = default; + + MergeableTH1OccupancyPerDECycle(MergeableTH1OccupancyPerDECycle const& copymerge) + : TH1F("DefaultNameCycle", "DefaultTitleCycle", 1100, -0.5, 1099.5), o2::mergers::MergeInterface(), mhistoNum(copymerge.getNum()), mhistoDen(copymerge.getDen()) + { + } + + MergeableTH1OccupancyPerDECycle(const char* name, const char* title, TH2F* histonum, TH2F* histoden) + : TH1F(name, title, 1100, -0.5, 1099.5), o2::mergers::MergeInterface(), mhistoNum(histonum), mhistoDen(histoden) + { + for (auto de : o2::mch::raw::deIdsForAllMCH) { + LastMeanNhitsDE[de] = 0; + LastMeanNorbitsDE[de] = 0; + } + update(); + } + + ~MergeableTH1OccupancyPerDECycle() override = default; + + void merge(MergeInterface* const other) override + { + mhistoNum->Add(dynamic_cast(other)->getNum()); + mhistoDen->Add(dynamic_cast(other)->getDen()); + + const double* ptrotherLastMeanNhitsDE = dynamic_cast(other)->getLastMeanNhitsDE(); + const double* ptrotherLastMeanNorbitsDE = dynamic_cast(other)->getLastMeanNorbitsDE(); + + for (auto de : o2::mch::raw::deIdsForAllMCH) { + LastMeanNhitsDE[de] += ptrotherLastMeanNhitsDE[de]; + LastMeanNorbitsDE[de] += ptrotherLastMeanNorbitsDE[de]; + } + + const double* ptrotherNewMeanNhitsDE = dynamic_cast(other)->getNewMeanNhitsDE(); + const double* ptrotherNewMeanNorbitsDE = dynamic_cast(other)->getNewMeanNorbitsDE(); + + for (auto de : o2::mch::raw::deIdsForAllMCH) { + NewMeanNhitsDE[de] += ptrotherNewMeanNhitsDE[de]; + NewMeanNorbitsDE[de] += ptrotherNewMeanNorbitsDE[de]; + } + + updateAfterMerge(); + } + + TH2F* getNum() const + { + return mhistoNum; + } + + TH2F* getDen() const + { + return mhistoDen; + } + + const double* getLastMeanNhitsDE() const + { + const double* ptrLastMeanNhitsDE = LastMeanNhitsDE; + return ptrLastMeanNhitsDE; + } + + const double* getLastMeanNorbitsDE() const + { + const double* ptrLastMeanNorbitsDE = LastMeanNorbitsDE; + return ptrLastMeanNorbitsDE; + } + + const double* getNewMeanNhitsDE() const + { + const double* ptrNewMeanNhitsDE = NewMeanNhitsDE; + return ptrNewMeanNhitsDE; + } + + const double* getNewMeanNorbitsDE() const + { + const double* ptrNewMeanNorbitsDE = NewMeanNorbitsDE; + return ptrNewMeanNorbitsDE; + } + + void update() + { + const char* name = this->GetName(); + const char* title = this->GetTitle(); + Reset(); + SetNameTitle(name, title); + + o2::mch::raw::Elec2DetMapper mElec2DetMapper = o2::mch::raw::createElec2DetMapper(); + o2::mch::raw::Det2ElecMapper mDet2ElecMapper = o2::mch::raw::createDet2ElecMapper(); + o2::mch::raw::FeeLink2SolarMapper mFeeLink2SolarMapper = o2::mch::raw::createFeeLink2SolarMapper(); + o2::mch::raw::Solar2FeeLinkMapper mSolar2FeeLinkMapper = o2::mch::raw::createSolar2FeeLinkMapper(); + + // Using NHitsElec and Norbits to get the mean occupancy per DE on last cycle + // Similarly, by looking at NHits and NOrbits Elec histogram, for each bin incrementing the corresponding DE total hits and total orbits, and from the values obtained at the end of a cycle compared to the beginning of the cycle, computing the occupancy during the cycle. + auto hhits = mhistoNum; + auto horbits = mhistoDen; + int NbinsDE[1100]{ 0 }; + if (hhits && horbits) { + for (auto de : o2::mch::raw::deIdsForAllMCH) { + LastMeanNhitsDE[de] = NewMeanNhitsDE[de]; + LastMeanNorbitsDE[de] = NewMeanNorbitsDE[de]; + NewMeanNhitsDE[de] = 0; + NewMeanNorbitsDE[de] = 0; + } + for (int binx = 1; binx < hhits->GetXaxis()->GetNbins() + 1; binx++) { + for (int biny = 1; biny < hhits->GetYaxis()->GetNbins() + 1; biny++) { + // Same procedure as above in getting Elec info + uint32_t dsAddr = (binx - 1) % 40; + uint32_t linkId = ((binx - 1 - dsAddr) / 40) % 12; + uint32_t feeId = (binx - 1 - dsAddr - 40 * linkId) / (12 * 40); + uint32_t de; + std::optional solarId = mFeeLink2SolarMapper(o2::mch::raw::FeeLinkId{ static_cast(feeId), static_cast(linkId) }); + if (!solarId.has_value()) { + continue; + } + std::optional dsDetId = + mElec2DetMapper(o2::mch::raw::DsElecId{ solarId.value(), static_cast(dsAddr / 5), static_cast(dsAddr % 5) }); + if (!dsDetId.has_value()) { + continue; + } + de = dsDetId->deId(); + + NewMeanNhitsDE[de] += hhits->GetBinContent(binx, biny); + NewMeanNorbitsDE[de] += horbits->GetBinContent(binx, biny); + NbinsDE[de] += 1; + } + } + for (auto i : o2::mch::raw::deIdsForAllMCH) { + double MeanOccupancyDECycle = 0; + if (NbinsDE[i] > 0) { + NewMeanNhitsDE[i] /= NbinsDE[i]; + NewMeanNorbitsDE[i] /= NbinsDE[i]; + } + if ((NewMeanNorbitsDE[i] - LastMeanNorbitsDE[i]) > 0) { + MeanOccupancyDECycle = (NewMeanNhitsDE[i] - LastMeanNhitsDE[i]) / (NewMeanNorbitsDE[i] - LastMeanNorbitsDE[i]) / 87.5; //Scaling to MHz + } + SetBinContent(i + 1, MeanOccupancyDECycle); + } + } + } + + void updateAfterMerge() + { + const char* name = this->GetName(); + const char* title = this->GetTitle(); + Reset(); + SetNameTitle(name, title); + + // Using NHitsElec and Norbits to get the mean occupancy per DE on last cycle + // Similarly, by looking at NHits and NOrbits Elec histogram, for each bin incrementing the corresponding DE total hits and total orbits, and from the values obtained at the end of a cycle compared to the beginning of the cycle, computing the occupancy during the cycle. + auto hhits = mhistoNum; + auto horbits = mhistoDen; + if (hhits && horbits) { + for (auto i : o2::mch::raw::deIdsForAllMCH) { + double MeanOccupancyDECycle = 0; + if ((NewMeanNorbitsDE[i] - LastMeanNorbitsDE[i]) > 0) { + MeanOccupancyDECycle = (NewMeanNhitsDE[i] - LastMeanNhitsDE[i]) / (NewMeanNorbitsDE[i] - LastMeanNorbitsDE[i]) / 87.5; //Scaling to MHz + } + SetBinContent(i + 1, MeanOccupancyDECycle); + } + } + } + + private: + TH2F* mhistoNum{ nullptr }; + TH2F* mhistoDen{ nullptr }; + std::string mTreatMeAs = "TH1F"; + double NewMeanNhitsDE[1100]{ 0 }; + double NewMeanNorbitsDE[1100]{ 0 }; + double LastMeanNhitsDE[1100]{ 0 }; + double LastMeanNorbitsDE[1100]{ 0 }; + + ClassDefOverride(MergeableTH1OccupancyPerDECycle, 1); +}; + +} // namespace o2::quality_control_modules::muonchambers + +#endif //O2_MERGEABLETH1OCCUPANCYPERDECYCLE_H diff --git a/Modules/MUON/MCH/include/MCH/MergeableTH1PseudoEfficiencyPerDE.h b/Modules/MUON/MCH/include/MCH/MergeableTH1PseudoEfficiencyPerDE.h new file mode 100644 index 0000000000..cdfb51e13d --- /dev/null +++ b/Modules/MUON/MCH/include/MCH/MergeableTH1PseudoEfficiencyPerDE.h @@ -0,0 +1,137 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MergeableTH1OccupancyPerDE.h +/// \brief An example of a custom TH2Quotient inheriting MergeInterface +/// +/// \author Piotr Konopka, piotr.jan.konopka@cern.ch, Sebastien Perrin + +#ifndef O2_MERGEABLETH1PSEUDOEFFICIENCYPERDE_H +#define O2_MERGEABLETH1PSEUDOEFFICIENCYPERDE_H + +#include +#include +#include +#include +#include +#include +#include + +#include "Mergers/MergeInterface.h" +#include "MCHRawElecMap/Mapper.h" +#ifdef HAVE_DIGIT_IN_DATAFORMATS +#include "DataFormatsMCH/Digit.h" +#else +#include "MCHBase/Digit.h" +#endif +#include "MCH/GlobalHistogram.h" + +using namespace std; +namespace o2::quality_control_modules::muonchambers +{ + +class MergeableTH1PseudoEfficiencyPerDE : public TH1F, public o2::mergers::MergeInterface +{ + public: + MergeableTH1PseudoEfficiencyPerDE() = default; + + MergeableTH1PseudoEfficiencyPerDE(MergeableTH1PseudoEfficiencyPerDE const& copymerge) + : TH1F("DefaultName", "DefaultTitle", 1100, -0.5, 1099.5), o2::mergers::MergeInterface(), mhistosNum(copymerge.getNum()), mhistosDen(copymerge.getDen()) + { + } + + MergeableTH1PseudoEfficiencyPerDE(const char* name, const char* title, std::map histosnum, std::map histosden) + : TH1F(name, title, 1100, -0.5, 1099.5), o2::mergers::MergeInterface(), mhistosNum(histosnum), mhistosDen(histosden) + { + update(); + } + + ~MergeableTH1PseudoEfficiencyPerDE() override = default; + + void merge(MergeInterface* const other) override + { + + for (auto de : o2::mch::raw::deIdsForAllMCH) { + auto hnum = dynamic_cast(other)->getNum().find(de); + auto hden = dynamic_cast(other)->getDen().find(de); + if ((hden != dynamic_cast(other)->getDen().end()) && (hden->second != NULL) && (hnum != dynamic_cast(other)->getNum().end()) && (hnum->second != NULL)) { + + auto hnumfinal = mhistosNum.find(de); + auto hdenfinal = mhistosDen.find(de); + if ((hdenfinal != mhistosDen.end()) && (hdenfinal->second != NULL) && (hnumfinal != mhistosNum.end()) && (hnumfinal->second != NULL)) { + hnumfinal->second->Add(hnum->second); + hdenfinal->second->Add(hden->second); + } + } + } + + update(); + } + + std::map getNum() const + { + return mhistosNum; + } + + std::map getDen() const + { + return mhistosDen; + } + + void update() + { + const char* name = this->GetName(); + const char* title = this->GetTitle(); + Reset(); + SetNameTitle(name, title); + + double NewPreclNumDE[1100]; + double NewPreclDenDE[1100]; + double MeanPseudoeffDE; + + for (auto de : o2::mch::raw::deIdsForAllMCH) { + auto hnum = mhistosNum.find(de); + auto hden = mhistosDen.find(de); + if ((hden != mhistosDen.end()) && (hden->second != NULL) && (hnum != mhistosNum.end()) && (hnum->second != NULL)) { + NewPreclNumDE[de] = 0; + NewPreclDenDE[de] = 0; + for (int binx = 1; binx < hden->second->GetXaxis()->GetNbins() + 1; binx++) { + for (int biny = 1; biny < hden->second->GetYaxis()->GetNbins() + 1; biny++) { + NewPreclDenDE[de] += hden->second->GetBinContent(binx, biny); + } + } + for (int binx = 1; binx < hnum->second->GetXaxis()->GetNbins() + 1; binx++) { + for (int biny = 1; biny < hnum->second->GetYaxis()->GetNbins() + 1; biny++) { + NewPreclNumDE[de] += hnum->second->GetBinContent(binx, biny); + } + } + } + } + + for (auto de : o2::mch::raw::deIdsForAllMCH) { + MeanPseudoeffDE = 0; + if (NewPreclDenDE[de] > 0) { + MeanPseudoeffDE = NewPreclNumDE[de] / NewPreclDenDE[de]; + } + SetBinContent(de + 1, MeanPseudoeffDE); + } + } + + private: + std::map mhistosNum; + std::map mhistosDen; + std::string mTreatMeAs = "TH1F"; + + ClassDefOverride(MergeableTH1PseudoEfficiencyPerDE, 1); +}; + +} // namespace o2::quality_control_modules::muonchambers + +#endif //O2_MERGEABLETH1PSEUDOEFFICIENCYPERDE_H diff --git a/Modules/MUON/MCH/include/MCH/MergeableTH1PseudoEfficiencyPerDECycle.h b/Modules/MUON/MCH/include/MCH/MergeableTH1PseudoEfficiencyPerDECycle.h new file mode 100644 index 0000000000..c130472732 --- /dev/null +++ b/Modules/MUON/MCH/include/MCH/MergeableTH1PseudoEfficiencyPerDECycle.h @@ -0,0 +1,205 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MergeableTH1OccupancyPerDE.h +/// \brief An example of a custom TH2Quotient inheriting MergeInterface +/// +/// \author Piotr Konopka, piotr.jan.konopka@cern.ch, Sebastien Perrin + +#ifndef O2_MERGEABLETH1PSEUDOEFFICIENCYPERDECYCLE_H +#define O2_MERGEABLETH1PSEUDOEFFICIENCYPERDECYCLE_H + +#include +#include +#include +#include +#include +#include +#include + +#include "Mergers/MergeInterface.h" +#include "MCHRawElecMap/Mapper.h" +#ifdef HAVE_DIGIT_IN_DATAFORMATS +#include "DataFormatsMCH/Digit.h" +#else +#include "MCHBase/Digit.h" +#endif + +using namespace std; +namespace o2::quality_control_modules::muonchambers +{ + +class MergeableTH1PseudoEfficiencyPerDECycle : public TH1F, public o2::mergers::MergeInterface +{ + public: + MergeableTH1PseudoEfficiencyPerDECycle() = default; + + MergeableTH1PseudoEfficiencyPerDECycle(MergeableTH1PseudoEfficiencyPerDECycle const& copymerge) + : TH1F("DefaultNameCycle", "DefaultTitleCycle", 1100, -0.5, 1099.5), o2::mergers::MergeInterface(), mhistosNum(copymerge.getNum()), mhistosDen(copymerge.getDen()) + { + } + + MergeableTH1PseudoEfficiencyPerDECycle(const char* name, const char* title, std::map histosnum, std::map histosden) + : TH1F(name, title, 1100, -0.5, 1099.5), o2::mergers::MergeInterface(), mhistosNum(histosnum), mhistosDen(histosden) + { + for (auto de : o2::mch::raw::deIdsForAllMCH) { + LastMeanNumDE[de] = 0; + LastMeanDenDE[de] = 0; + } + update(); + } + + ~MergeableTH1PseudoEfficiencyPerDECycle() override = default; + + void merge(MergeInterface* const other) override + { //FIXME + for (auto de : o2::mch::raw::deIdsForAllMCH) { + auto hnum = dynamic_cast(other)->getNum().find(de); + auto hden = dynamic_cast(other)->getDen().find(de); + if ((hden != dynamic_cast(other)->getDen().end()) && (hden->second != NULL) && (hnum != dynamic_cast(other)->getNum().end()) && (hnum->second != NULL)) { + + auto hnumfinal = mhistosNum.find(de); + auto hdenfinal = mhistosDen.find(de); + if ((hdenfinal != mhistosDen.end()) && (hdenfinal->second != NULL) && (hnumfinal != mhistosNum.end()) && (hnumfinal->second != NULL)) { + hnumfinal->second->Add(hnum->second); + hdenfinal->second->Add(hden->second); + } + } + } + + const double* ptrotherLastMeanNumDE = dynamic_cast(other)->getLastMeanNumDE(); + const double* ptrotherLastMeanDenDE = dynamic_cast(other)->getLastMeanDenDE(); + + for (auto de : o2::mch::raw::deIdsForAllMCH) { + LastMeanNumDE[de] += ptrotherLastMeanNumDE[de]; + LastMeanDenDE[de] += ptrotherLastMeanDenDE[de]; + } + + const double* ptrotherNewMeanNumDE = dynamic_cast(other)->getNewMeanNumDE(); + const double* ptrotherNewMeanDenDE = dynamic_cast(other)->getNewMeanDenDE(); + + for (auto de : o2::mch::raw::deIdsForAllMCH) { + NewMeanNumDE[de] += ptrotherNewMeanNumDE[de]; + NewMeanDenDE[de] += ptrotherNewMeanDenDE[de]; + } + + updateAfterMerge(); + } + + std::map getNum() const + { + return mhistosNum; + } + + std::map getDen() const + { + return mhistosDen; + } + + const double* getLastMeanNumDE() const + { + const double* ptrLastMeanNumDE = LastMeanNumDE; + return ptrLastMeanNumDE; + } + + const double* getLastMeanDenDE() const + { + const double* ptrLastMeanDenDE = LastMeanDenDE; + return ptrLastMeanDenDE; + } + + const double* getNewMeanNumDE() const + { + const double* ptrNewMeanNumDE = NewMeanNumDE; + return ptrNewMeanNumDE; + } + + const double* getNewMeanDenDE() const + { + const double* ptrNewMeanDenDE = NewMeanDenDE; + return ptrNewMeanDenDE; + } + + void update() + { + const char* name = this->GetName(); + const char* title = this->GetTitle(); + Reset(); + SetNameTitle(name, title); + + for (auto de : o2::mch::raw::deIdsForAllMCH) { + + LastMeanNumDE[de] = NewMeanNumDE[de]; + LastMeanDenDE[de] = NewMeanDenDE[de]; + NewMeanNumDE[de] = 0; + NewMeanDenDE[de] = 0; + + auto hnum = mhistosNum.find(de); + auto hden = mhistosDen.find(de); + if ((hden != mhistosDen.end()) && (hden->second != NULL) && (hnum != mhistosNum.end()) && (hnum->second != NULL)) { + for (int binx = 1; binx < hden->second->GetXaxis()->GetNbins() + 1; binx++) { + for (int biny = 1; biny < hden->second->GetYaxis()->GetNbins() + 1; biny++) { + NewMeanDenDE[de] += hden->second->GetBinContent(binx, biny); + } + } + for (int binx = 1; binx < hnum->second->GetXaxis()->GetNbins() + 1; binx++) { + for (int biny = 1; biny < hnum->second->GetYaxis()->GetNbins() + 1; biny++) { + NewMeanNumDE[de] += hnum->second->GetBinContent(binx, biny); + } + } + } + } + + for (auto de : o2::mch::raw::deIdsForAllMCH) { + double MeanPseudoeffDECycle = 0; + if ((NewMeanNumDE[de] - LastMeanNumDE[de]) > 0) { + MeanPseudoeffDECycle = (NewMeanNumDE[de] - LastMeanNumDE[de]) / (NewMeanDenDE[de] - LastMeanDenDE[de]); + } + SetBinContent(de + 1, MeanPseudoeffDECycle); + } + } + + void updateAfterMerge() + { + const char* name = this->GetName(); + const char* title = this->GetTitle(); + Reset(); + SetNameTitle(name, title); + + // Using NHitsElec and Norbits to get the mean occupancy per DE on last cycle + // Similarly, by looking at NHits and NOrbits Elec histogram, for each bin incrementing the corresponding DE total hits and total orbits, and from the values obtained at the end of a cycle compared to the beginning of the cycle, computing the occupancy during the cycle. + for (auto i : o2::mch::raw::deIdsForAllMCH) { + auto hnum = mhistosNum.find(i); + auto hden = mhistosDen.find(i); + if ((hden != mhistosDen.end()) && (hden->second != NULL) && (hnum != mhistosNum.end()) && (hnum->second != NULL)) { + double MeanPseudoEfficiencyDECycle = 0; + if ((NewMeanDenDE[i] - LastMeanDenDE[i]) > 0) { + MeanPseudoEfficiencyDECycle = (NewMeanNumDE[i] - LastMeanNumDE[i]) / (NewMeanDenDE[i] - LastMeanDenDE[i]); + } + SetBinContent(i + 1, MeanPseudoEfficiencyDECycle); + } + } + } + + private: + std::map mhistosNum; + std::map mhistosDen; + std::string mTreatMeAs = "TH1F"; + double NewMeanNumDE[1100]{ 0 }; + double NewMeanDenDE[1100]{ 0 }; + double LastMeanNumDE[1100]{ 0 }; + double LastMeanDenDE[1100]{ 0 }; + + ClassDefOverride(MergeableTH1PseudoEfficiencyPerDECycle, 1); +}; + +} // namespace o2::quality_control_modules::muonchambers + +#endif //O2_MERGEABLETH1PSEUDOEFFICIENCYPERDECYCLE_H diff --git a/Modules/MUON/MCH/include/MCH/MergeableTH2Ratio.h b/Modules/MUON/MCH/include/MCH/MergeableTH2Ratio.h index 126fdc351e..d6ad9bc164 100644 --- a/Modules/MUON/MCH/include/MCH/MergeableTH2Ratio.h +++ b/Modules/MUON/MCH/include/MCH/MergeableTH2Ratio.h @@ -34,12 +34,12 @@ class MergeableTH2Ratio : public TH2F, public o2::mergers::MergeInterface MergeableTH2Ratio() = default; MergeableTH2Ratio(MergeableTH2Ratio const& copymerge) - : TH2F(*(copymerge.getNum())), o2::mergers::MergeInterface(), mhistoNum(copymerge.getNum()), mhistoDen(copymerge.getDen()) + : TH2F(*(copymerge.getNum())), o2::mergers::MergeInterface(), mhistoNum(copymerge.getNum()), mhistoDen(copymerge.getDen()), mlistOfFunctions(copymerge.getNum()->GetListOfFunctions()), mScalingFactor(copymerge.getScalingFactor()) { } - MergeableTH2Ratio(const char* name, const char* title, TH2F* histonum, TH2F* histoden) - : TH2F(*histonum), o2::mergers::MergeInterface(), mhistoNum(histonum), mhistoDen(histoden) + MergeableTH2Ratio(const char* name, const char* title, TH2F* histonum, TH2F* histoden, double scaling = 1.) + : TH2F(*histonum), o2::mergers::MergeInterface(), mhistoNum(histonum), mhistoDen(histoden), mlistOfFunctions(mhistoNum->GetListOfFunctions()), mScalingFactor(scaling) { SetNameTitle(name, title); update(); @@ -64,6 +64,11 @@ class MergeableTH2Ratio : public TH2F, public o2::mergers::MergeInterface return mhistoDen; } + double getScalingFactor() const + { + return mScalingFactor; + } + void update() { static constexpr double sOrbitLengthInNanoseconds = 3564 * 25; @@ -72,17 +77,30 @@ class MergeableTH2Ratio : public TH2F, public o2::mergers::MergeInterface const char* name = this->GetName(); const char* title = this->GetTitle(); Reset(); + //if(mlistOfFunctions->GetLast() > 0){ + // beautify(); + //} Divide(mhistoNum, mhistoDen); SetNameTitle(name, title); // convertion to KHz units - Scale(1. / sOrbitLengthInMilliseconds); + if (mScalingFactor != 1.) { + Scale(1. / sOrbitLengthInMilliseconds); + } SetOption("colz"); } + void beautify() + { + GetListOfFunctions()->RemoveAll(); + GetListOfFunctions()->AddAll(mlistOfFunctions); + } + private: TH2F* mhistoNum{ nullptr }; TH2F* mhistoDen{ nullptr }; + TList* mlistOfFunctions{ nullptr }; std::string mTreatMeAs = "TH2F"; + double mScalingFactor = 1.; ClassDefOverride(MergeableTH2Ratio, 1); }; diff --git a/Modules/MUON/MCH/include/MCH/PedestalsTask.h b/Modules/MUON/MCH/include/MCH/PedestalsTask.h index c181a3ad84..2c8b6f501b 100644 --- a/Modules/MUON/MCH/include/MCH/PedestalsTask.h +++ b/Modules/MUON/MCH/include/MCH/PedestalsTask.h @@ -63,8 +63,8 @@ class PedestalsTask final : public TaskInterface std::map mHistogramPedestalsDE; std::map mHistogramNoiseDE; - std::map mHistogramPedestalsXY[2]; - std::map mHistogramNoiseXY[2]; + std::map mHistogramPedestalsXY[2]; + std::map mHistogramNoiseXY[2]; std::map mHistogramNoiseDistributionDE[5][2]; diff --git a/Modules/MUON/MCH/include/MCH/PhysicsOccupancyCheck.h b/Modules/MUON/MCH/include/MCH/PhysicsOccupancyCheck.h new file mode 100644 index 0000000000..bea7495208 --- /dev/null +++ b/Modules/MUON/MCH/include/MCH/PhysicsOccupancyCheck.h @@ -0,0 +1,53 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file PhysicsCheck.h +/// \author Andrea Ferrero, Sebastien Perrin +/// + +#ifndef QC_MODULE_MCH_PHYSICSOCCUPANCYCHECK_H +#define QC_MODULE_MCH_PHYSICSOCCUPANCYCHECK_H + +#include "QualityControl/CheckInterface.h" +#include "QualityControl/MonitorObject.h" +#include "QualityControl/Quality.h" +#include + +namespace o2::quality_control_modules::muonchambers +{ + +/// \brief Check if the occupancy from trending is between the two specified values +/// +/// \author Andrea Ferrero, Sebastien Perrin +class PhysicsOccupancyCheck : public o2::quality_control::checker::CheckInterface +{ + public: + /// Default constructor + PhysicsOccupancyCheck(); + /// Destructor + ~PhysicsOccupancyCheck() override; + + // Override interface + void configure(std::string name) override; + Quality check(std::map>* moMap) override; + void beautify(std::shared_ptr mo, Quality checkResult = Quality::Null) override; + std::string getAcceptedType() override; + + private: + int mPrintLevel; + double minOccupancy; + double maxOccupancy; + ClassDefOverride(PhysicsOccupancyCheck, 1); +}; + +} // namespace o2::quality_control_modules::muonchambers + +#endif // QC_MODULE_TOF_TOFCHECKRAWSTIME_H diff --git a/Modules/MUON/MCH/include/MCH/PhysicsPreclustersCheck.h b/Modules/MUON/MCH/include/MCH/PhysicsPreclustersCheck.h new file mode 100644 index 0000000000..e135c06a64 --- /dev/null +++ b/Modules/MUON/MCH/include/MCH/PhysicsPreclustersCheck.h @@ -0,0 +1,55 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file PhysicsCheck.h +/// \author Andrea Ferrero, Sebastien Perrin +/// + +#ifndef QC_MODULE_MCH_PHYSICSPRECLUSTERSCHECK_H +#define QC_MODULE_MCH_PHYSICSPRECLUSTERSCHECK_H + +#include "QualityControl/CheckInterface.h" +#include "QualityControl/MonitorObject.h" +#include "QualityControl/Quality.h" +#include + +namespace o2::quality_control_modules::muonchambers +{ + +/// \brief Check if the occupancy from trending is between the two specified values +/// +/// \author Andrea Ferrero, Sebastien Perrin +class PhysicsPreclustersCheck : public o2::quality_control::checker::CheckInterface +{ + public: + /// Default constructor + PhysicsPreclustersCheck(); + /// Destructor + ~PhysicsPreclustersCheck() override; + + // Override interface + void configure(std::string name) override; + Quality check(std::map>* moMap) override; + void beautify(std::shared_ptr mo, Quality checkResult = Quality::Null) override; + std::string getAcceptedType() override; + + private: + int mPrintLevel; + double minPseudoeff; + double maxPseudoeff; + double minMPV; + double maxMPV; + ClassDefOverride(PhysicsPreclustersCheck, 1); +}; + +} // namespace o2::quality_control_modules::muonchambers + +#endif // QC_MODULE_TOF_TOFCHECKRAWSTIME_H diff --git a/Modules/MUON/MCH/include/MCH/PhysicsTaskDigits.h b/Modules/MUON/MCH/include/MCH/PhysicsTaskDigits.h index 0aa5233e91..97b1987cc3 100644 --- a/Modules/MUON/MCH/include/MCH/PhysicsTaskDigits.h +++ b/Modules/MUON/MCH/include/MCH/PhysicsTaskDigits.h @@ -28,6 +28,8 @@ #endif #include "MCH/GlobalHistogram.h" #include "MCH/MergeableTH2Ratio.h" +#include "MCH/MergeableTH1OccupancyPerDE.h" +#include "MCH/MergeableTH1OccupancyPerDECycle.h" class TH1F; class TH2F; @@ -85,13 +87,17 @@ class PhysicsTaskDigits /*final*/ : public TaskInterface // todo add back the "f MergeableTH2Ratio* mHistogramOccupancyElec; // Mergeable object, Occupancy histogram (Elec view) std::map mHistogramADCamplitudeDE; // Histogram of ADC distribution per DE - std::map mHistogramNhitsDE[2]; // Histogram of Number of hits (XY view) - std::map mHistogramNorbitsDE[2]; // Histogram of Number of orbits (XY view) + std::map mHistogramNhitsDE[2]; // Histogram of Number of hits (XY view) + std::map mHistogramNorbitsDE[2]; // Histogram of Number of orbits (XY view) std::map mHistogramOccupancyDE[2]; // Mergeable object, Occupancy histogram (XY view) GlobalHistogram* mHistogramNHitsAllDE; // Global histogram (all DE) of Number of hits GlobalHistogram* mHistogramOrbitsAllDE; // Global histogram (all DE) of Number of orbits MergeableTH2Ratio* mHistogramOccupancyAllDE; //Mergeable object, Global histogram (all DE) of Occupancy + + // TH1 of the Mean Occupancy on each DE, integrated or only on elapsed cycle - Sent for Trending + MergeableTH1OccupancyPerDE* mMeanOccupancyPerDE; + MergeableTH1OccupancyPerDECycle* mMeanOccupancyPerDECycle; }; } // namespace muonchambers diff --git a/Modules/MUON/MCH/include/MCH/PhysicsTaskPreclusters.h b/Modules/MUON/MCH/include/MCH/PhysicsTaskPreclusters.h index d922420c15..f2d74f65c5 100644 --- a/Modules/MUON/MCH/include/MCH/PhysicsTaskPreclusters.h +++ b/Modules/MUON/MCH/include/MCH/PhysicsTaskPreclusters.h @@ -24,12 +24,16 @@ #include #include "QualityControl/TaskInterface.h" #include "MCH/GlobalHistogram.h" -#if HAVE_DIGIT_IN_DATAFORMATS +#ifdef HAVE_DIGIT_IN_DATAFORMATS #include "DataFormatsMCH/Digit.h" #else #include "MCHBase/Digit.h" #endif #include "MCHBase/PreCluster.h" +#include "MCH/MergeableTH2Ratio.h" +#include "MCH/MergeableTH1PseudoEfficiencyPerDE.h" +#include "MCH/MergeableTH1PseudoEfficiencyPerDECycle.h" +#include "MCH/MergeableTH1MPVPerDECycle.h" namespace o2 { @@ -59,31 +63,37 @@ class PhysicsTaskPreclusters /*final*/ : public o2::quality_control::core::TaskI void reset() override; bool plotPrecluster(const o2::mch::PreCluster& preCluster, gsl::span digits); + void printPrecluster(gsl::span preClusterDigits); void printPreclusters(gsl::span preClusters, gsl::span digits); - private: - double MeanPseudoeffDE[1100]; - double MeanPseudoeffDECycle[1100]; - // Arrays needed to compute the Pseudo-efficiency on the elapsed cycle - double LastPreclBNBDE[1100]; - double NewPreclBNBDE[1100]; - double LastPreclNumDE[1100]; - double NewPreclNumDE[1100]; + void computePseudoEfficiency(); + private: std::vector> digits; - // TH1 of Mean Pseudo-efficiency on DEs, integrated or only on the elapsed cycle - Sent for Trending - TH1F* mMeanPseudoeffPerDE; - TH1F* mMeanPseudoeffPerDECycle; + // TH1 of Mean Pseudo-efficiency on DEs + //Since beginning of run + MergeableTH1PseudoEfficiencyPerDE* mMeanPseudoeffPerDE_DoesGoodNBHaveSomethingB; //Pseudoefficiency of NB (Good cluster on NB And data on B / Good cluster on NB) + MergeableTH1PseudoEfficiencyPerDE* mMeanPseudoeffPerDE_DoesGoodBHaveSomethingNB; //Pseudoefficiency of B (Good cluster on B And data on NB / Good cluster on B) + + //On last cycle only + MergeableTH1PseudoEfficiencyPerDECycle* mMeanPseudoeffPerDE_DoesGoodNBHaveSomethingB_Cycle; + MergeableTH1PseudoEfficiencyPerDECycle* mMeanPseudoeffPerDE_DoesGoodBHaveSomethingNB_Cycle; + MergeableTH1MPVPerDECycle* mMPVCycle; //MPV of the Landau best fitted to the cluster charge distribution on each DE each cycle + + TH2F* mDigitChargeVsSize[4]; + TH2F* mDigitClsizeVsCharge[2]; + TH2F* mDigitChargeNBVsChargeB; - std::map mHistogramClchgDE; + std::map mHistogramClchgDE; std::map mHistogramClchgDEOnCycle; - std::map mHistogramClsizeDE; + std::map mHistogramClsizeDE; - std::map mHistogramPreclustersXY[4]; - std::map mHistogramPseudoeffXY[3]; + std::map mHistogramPreclustersXY[4]; + std::map mHistogramPseudoeffXY[2]; - GlobalHistogram* mHistogramPseudoeff[3]; + GlobalHistogram* mHistogramPseudoeff_NumsAndDens[2]; //Global histograms containing the numerators and denominators for Pseudoefficiency calculation + MergeableTH2Ratio* mHistogramPseudoeff; //Mergeable histogram of Pseudoefficiency }; } // namespace muonchambers diff --git a/Modules/MUON/MCH/src/GlobalHistogram.cxx b/Modules/MUON/MCH/src/GlobalHistogram.cxx index 002eaf9fe6..e09a12d8fa 100644 --- a/Modules/MUON/MCH/src/GlobalHistogram.cxx +++ b/Modules/MUON/MCH/src/GlobalHistogram.cxx @@ -20,6 +20,8 @@ #include #include +#include + #include "MCHMappingInterface/Segmentation.h" #include "MCHMappingInterface/CathodeSegmentation.h" #ifdef MCH_HAS_MAPPING_FACTORY @@ -48,8 +50,177 @@ namespace quality_control_modules namespace muonchambers { +std::string getHistoPath(int deId) +{ + return fmt::format("ST{}/DE{}/", (deId - 100) / 200 + 1, deId); +} + +static int getLR(int de) +{ + int lr = -1; + int deId = de % 100; + if ((de >= 100) && (de < 500)) { + if ((deId >= 1) && (deId <= 2)) { + // ST12 left + lr = 0; + } else { + lr = 1; + } + } + if ((de >= 500) && (de < 700)) { + if (((deId >= 0) && (deId <= 4)) || ((deId >= 14) && (deId <= 17))) { + // ST3 right + lr = 1; + } + if (((deId >= 5) && (deId <= 13))) { + // ST3 left + lr = 0; + } + } + if ((de >= 700) && (de < 1100)) { + if (((deId >= 0) && (deId <= 6)) || ((deId >= 20) && (deId <= 25))) { + // ST4/5 right + lr = 1; + } + if (((deId >= 7) && (deId <= 19))) { + // ST4/5 left + lr = 0; + } + } + return lr; +} + +static int getBT(int de) +{ + int bt = -1; + int deId = de % 100; + if ((de >= 100) && (de < 500)) { + if ((deId == 0) || (deId == 1)) { + // ST12 top + bt = 1; + } else { + bt = 0; + } + } + return bt; +} + +static int getDetectorHistWidth(int deId) +{ + if (deId >= 500) { + return (40 * 5); + } else { + return (300); + } + return 10; +} + +static int getDetectorHistXbins(int deId) +{ + return (getDetectorHistWidth(deId) * 2); +} + +static int getDetectorHistHeight(int deId) +{ + if (deId >= 500) { + return (50); + } else { + return (300); + } + return 10; +} + +static int getDetectorHistYbins(int deId) +{ + return (getDetectorHistHeight(deId) * 2); +} + +static bool getDetectorFlipX(int deId) +{ + int lr = getLR(deId); + if (lr == 1) { + return true; + } + return false; +} + +static bool getDetectorFlipY(int deId) +{ + if (deId >= 100 && deId < 500) { + int bt = getBT(deId); + if (bt == 0) { + return true; + } + } + if (deId == 510 || deId == 517 || deId == 610 || deId == 617) { + return true; + } + if (deId >= 700) { + if ((deId % 100) == 14) { + return true; + } + if ((deId % 100) == 25) { + return true; + } + } + return false; +} + +DetectorHistogram::DetectorHistogram(TString name, TString title, int deId) : TH2F(name, title, + getDetectorHistXbins(deId), -1.0 * getDetectorHistWidth(deId) / 2, getDetectorHistWidth(deId) / 2, + getDetectorHistYbins(deId), -1.0 * getDetectorHistHeight(deId) / 2, getDetectorHistHeight(deId) / 2), + mDeId(deId), + mFlipX(getDetectorFlipX(deId)), + mFlipY(getDetectorFlipY(deId)) +{ + SetDrawOption("colz"); +} + +void DetectorHistogram::Fill(double padX, double padY, double padSizeX, double padSizeY, double val) +{ + if (mFlipX) { + padX *= -1.0; + } + if (mFlipY) { + padY *= -1.0; + } + + int binx_min = GetXaxis()->FindBin(padX - padSizeX / 2 + 0.1); + int binx_max = GetXaxis()->FindBin(padX + padSizeX / 2 - 0.1); + int biny_min = GetYaxis()->FindBin(padY - padSizeY / 2 + 0.1); + int biny_max = GetYaxis()->FindBin(padY + padSizeY / 2 - 0.1); + for (int by = biny_min; by <= biny_max; by++) { + float y = GetYaxis()->GetBinCenter(by); + for (int bx = binx_min; bx <= binx_max; bx++) { + float x = GetXaxis()->GetBinCenter(bx); + TH2F::Fill(x, y, val); + } + } +} + +void DetectorHistogram::Set(double padX, double padY, double padSizeX, double padSizeY, double val) +{ + if (mFlipX) { + padX *= -1.0; + } + if (mFlipY) { + padY *= -1.0; + } + + int binx_min = GetXaxis()->FindBin(padX - padSizeX / 2 + 0.1); + int binx_max = GetXaxis()->FindBin(padX + padSizeX / 2 - 0.1); + int biny_min = GetYaxis()->FindBin(padY - padSizeY / 2 + 0.1); + int biny_max = GetYaxis()->FindBin(padY + padSizeY / 2 - 0.1); + for (int by = biny_min; by <= biny_max; by++) { + for (int bx = binx_min; bx <= binx_max; bx++) { + TH2F::SetBinContent(bx, by, val); + } + } +} + GlobalHistogram::GlobalHistogram(std::string name, std::string title) : TH2F(name.c_str(), title.c_str(), HIST_WIDTH / HIST_SCALE, 0, HIST_WIDTH, HIST_HEIGHT / HIST_SCALE, 0, HIST_HEIGHT) { + SetDrawOption("colz"); } void GlobalHistogram::init() @@ -87,10 +258,16 @@ void GlobalHistogram::init() float xB0, yB0, xNB0, yNB0; getDeCenter(de, xB0, yB0, xNB0, yNB0); bool isR = getLR(de) == 1; + bool flipY = getDetectorFlipY(de); for (unsigned int vi = 0; vi < vertices.size(); vi++) { - const o2::mch::contour::Vertex v1 = vertices[vi]; - const o2::mch::contour::Vertex v2 = (vi < (vertices.size() - 1)) ? vertices[vi + 1] : vertices[0]; + o2::mch::contour::Vertex v1 = vertices[vi]; + o2::mch::contour::Vertex v2 = (vi < (vertices.size() - 1)) ? vertices[vi + 1] : vertices[0]; + + if (flipY) { + v1.y *= -1; + v2.y *= -1; + } if (isR) { line = new TLine(-v1.x + xB0, v1.y + yB0, -v2.x + xB0, v2.y + yB0); @@ -122,33 +299,6 @@ void GlobalHistogram::getDeCenter(int de, float& xB0, float& yB0, float& xNB0, f } } -int GlobalHistogram::getLR(int de) -{ - int lr = -1; - int deId = de % 100; - if ((de >= 500) && (de < 700)) { - if (((deId >= 0) && (deId <= 4)) || ((deId >= 14) && (deId <= 17))) { - // ST3 right - lr = 1; - } - if (((deId >= 5) && (deId <= 13))) { - // ST3 left - lr = 0; - } - } - if ((de >= 700) && (de < 1100)) { - if (((deId >= 0) && (deId <= 6)) || ((deId >= 20) && (deId <= 25))) { - // ST4/5 right - lr = 1; - } - if (((deId >= 7) && (deId <= 19))) { - // ST4/5 left - lr = 0; - } - } - return lr; -} - void GlobalHistogram::getDeCenterST3(int de, float& xB0, float& yB0, float& xNB0, float& yNB0) { int yOffset = 2; @@ -227,11 +377,19 @@ void GlobalHistogram::getDeCenterST3(int de, float& xB0, float& yB0, float& xNB0 // ST3 left, shift all detectors to the right xB0 += 120 - xmax; xNB0 += 120 - xmax; + if (deId == 9) { + xB0 -= 22.5; + xNB0 -= 22.5; + } } if (xId == 1) { // ST3 right, shift all detectors to the left xB0 -= 120 - xmax; xNB0 -= 120 - xmax; + if (deId == 0) { + xB0 += 22.5; + xNB0 += 22.5; + } } } @@ -333,11 +491,19 @@ void GlobalHistogram::getDeCenterST4(int de, float& xB0, float& yB0, float& xNB0 // ST3 left, shift all detectors to the right xB0 += 120 - xmax; xNB0 += 120 - xmax; + if (deId == 13) { + xB0 -= 40; + xNB0 -= 40; + } } if (xId == 1) { // ST3 right, shift all detectors to the left xB0 -= 120 - xmax; xNB0 -= 120 - xmax; + if (deId == 0) { + xB0 += 40; + xNB0 += 40; + } } } @@ -348,17 +514,17 @@ void GlobalHistogram::getDeCenterST5(int de, float& xB0, float& yB0, float& xNB0 xNB0 += NXHIST_PER_STATION * DE_WIDTH; } -void GlobalHistogram::add(std::map& histB, std::map& histNB) +void GlobalHistogram::add(std::map& histB, std::map& histNB) { set(histB, histNB, false); } -void GlobalHistogram::set_includeNull(std::map& histB, std::map& histNB) +void GlobalHistogram::set_includeNull(std::map& histB, std::map& histNB) { set(histB, histNB, true, true); } -void GlobalHistogram::set(std::map& histB, std::map& histNB, bool doAverage, bool includeNullBins) +void GlobalHistogram::set(std::map& histB, std::map& histNB, bool doAverage, bool includeNullBins) { for (auto& ih : histB) { int de = ih.first; @@ -372,17 +538,13 @@ void GlobalHistogram::set(std::map& histB, std::map& his continue; } - bool swapX = getLR(de) == 1; - - //std::cout<<"[GlobalHistogram::set] de="<startPublishing(mHistogramPedestals); - mHistogramPedestalsMCH = new GlobalHistogram("QcMuonChambers_Pedestals_AllDE", "Pedestals"); + mHistogramPedestalsMCH = new GlobalHistogram("Pedestals_AllDE", "Pedestals"); mHistogramPedestalsMCH->init(); getObjectsManager()->startPublishing(mHistogramPedestalsMCH); - mHistogramNoise = new TH2F("QcMuonChambers_Noise", "QcMuonChambers - Noise", + mHistogramNoise = new TH2F("QcMuonChambers_Noise", "Noise", (MCH_FFEID_MAX + 1) * 12 * 40, 0, (MCH_FFEID_MAX + 1) * 12 * 40, 64, 0, 64); getObjectsManager()->startPublishing(mHistogramNoise); - mHistogramNoiseMCH = new GlobalHistogram("QcMuonChambers_Noise_AllDE", "Noise"); + mHistogramNoiseMCH = new GlobalHistogram("Noise_AllDE", "Noise"); mHistogramNoiseMCH->init(); getObjectsManager()->startPublishing(mHistogramNoiseMCH); for (auto de : o2::mch::raw::deIdsForAllMCH) { - TH2F* hPedDE = new TH2F(TString::Format("QcMuonChambers_Pedestals_DE%03d", de), - TString::Format("QcMuonChambers - Pedestals (DE%03d)", de), 2000, 0, 2000, 64, 0, 64); + TH2F* hPedDE = new TH2F(TString::Format("Pedestals_Elec_DE%03d", de), + TString::Format("Pedestals (DE%03d)", de), 2000, 0, 2000, 64, 0, 64); mHistogramPedestalsDE.insert(make_pair(de, hPedDE)); - TH2F* hNoiseDE = new TH2F(TString::Format("QcMuonChambers_Noise_DE%03d", de), - TString::Format("QcMuonChambers - Noise (DE%03d)", de), 2000, 0, 2000, 64, 0, 64); + TH2F* hNoiseDE = new TH2F(TString::Format("Noise_Elec_DE%03d", de), + TString::Format("Noise (DE%03d)", de), 2000, 0, 2000, 64, 0, 64); mHistogramNoiseDE.insert(make_pair(de, hNoiseDE)); for (int pi = 0; pi < 5; pi++) { - TH1F* hNoiseDE = new TH1F(TString::Format("QcMuonChambers_Noise_Distr_DE%03d_b_%d", de, pi), - TString::Format("QcMuonChambers - Noise distribution (DE%03d B, %d)", de, pi), 1000, 0, 10); + TH1F* hNoiseDE = new TH1F(TString::Format("Noise_Distr_DE%03d_b_%d", de, pi), + TString::Format("Noise distribution (DE%03d B, %d)", de, pi), 1000, 0, 10); mHistogramNoiseDistributionDE[pi][0].insert(make_pair(de, hNoiseDE)); - hNoiseDE = new TH1F(TString::Format("QcMuonChambers_Noise_Distr_DE%03d_nb_%d", de, pi), - TString::Format("QcMuonChambers - Noise distribution (DE%03d NB, %d)", de, pi), 1000, 0, 10); + hNoiseDE = new TH1F(TString::Format("Noise_Distr_DE%03d_nb_%d", de, pi), + TString::Format("Noise distribution (DE%03d NB, %d)", de, pi), 1000, 0, 10); mHistogramNoiseDistributionDE[pi][1].insert(make_pair(de, hNoiseDE)); } - float Xsize = 50 * 5; - float Xsize2 = Xsize / 2; - float Ysize = 50; - float Ysize2 = Ysize / 2; { - TH2F* hPedXY = new TH2F(TString::Format("QcMuonChambers_Pedestals_XYb_%03d", de), - TString::Format("QcMuonChambers - Pedestals XY (DE%03d B)", de), Xsize * 2, -Xsize2, Xsize2, Ysize * 2, -Ysize2, Ysize2); + DetectorHistogram* hPedXY = new DetectorHistogram(TString::Format("%sPedestals_%03d_B", getHistoPath(de).c_str(), de), + TString::Format("Pedestals (DE%03d B)", de), de); mHistogramPedestalsXY[0].insert(make_pair(de, hPedXY)); - TH2F* hNoiseXY = new TH2F(TString::Format("QcMuonChambers_Noise_XYb_%03d", de), - TString::Format("QcMuonChambers - Noise XY (DE%03d B)", de), Xsize * 2, -Xsize2, Xsize2, Ysize * 2, -Ysize2, Ysize2); + getObjectsManager()->startPublishing(hPedXY); + DetectorHistogram* hNoiseXY = new DetectorHistogram(TString::Format("%sNoise_%03d_B", getHistoPath(de).c_str(), de), + TString::Format("Noise (DE%03d B)", de), de); mHistogramNoiseXY[0].insert(make_pair(de, hNoiseXY)); + getObjectsManager()->startPublishing(hNoiseXY); } { - TH2F* hPedXY = new TH2F(TString::Format("QcMuonChambers_Pedestals_XYnb_%03d", de), - TString::Format("QcMuonChambers - Pedestals XY (DE%03d NB)", de), Xsize * 2, -Xsize2, Xsize2, Ysize * 2, -Ysize2, Ysize2); + DetectorHistogram* hPedXY = new DetectorHistogram(TString::Format("%sPedestals_%03d_NB", getHistoPath(de).c_str(), de), + TString::Format("Pedestals (DE%03d NB)", de), de); mHistogramPedestalsXY[1].insert(make_pair(de, hPedXY)); - TH2F* hNoiseXY = new TH2F(TString::Format("QcMuonChambers_Noise_XYnb_%03d", de), - TString::Format("QcMuonChambers - Noise XY (DE%03d NB)", de), Xsize * 2, -Xsize2, Xsize2, Ysize * 2, -Ysize2, Ysize2); + getObjectsManager()->startPublishing(hPedXY); + DetectorHistogram* hNoiseXY = new DetectorHistogram(TString::Format("%sNoise_%03d_NB", getHistoPath(de).c_str(), de), + TString::Format("Noise (DE%03d NB)", de), de); mHistogramNoiseXY[1].insert(make_pair(de, hNoiseXY)); + getObjectsManager()->startPublishing(hNoiseXY); } } @@ -192,7 +192,7 @@ void PedestalsTask::fill_noise_distributions() void PedestalsTask::save_histograms() { - TFile f("/tmp/qc.root", "RECREATE"); + TFile f("mch-qc-pedestals.root", "RECREATE"); fill_noise_distributions(); mHistogramPedestalsMCH->Write(); @@ -239,7 +239,6 @@ void PedestalsTask::save_histograms() } } - f.ls(); f.Close(); } @@ -282,34 +281,18 @@ void PedestalsTask::PlotPedestalDE(uint16_t solarID, uint8_t dsID, uint8_t chann double padX = segment.padPositionX(padId); double padY = segment.padPositionY(padId); - float padSizeX = segment.padSizeX(padId); - float padSizeY = segment.padSizeY(padId); + double padSizeX = segment.padSizeX(padId); + double padSizeY = segment.padSizeY(padId); int cathode = segment.isBendingPad(padId) ? 0 : 1; // Fill the histograms for each detection element auto hPedXY = mHistogramPedestalsXY[cathode].find(deId); if ((hPedXY != mHistogramPedestalsXY[cathode].end()) && (hPedXY->second != NULL)) { - int binx_min = hPedXY->second->GetXaxis()->FindBin(padX - padSizeX / 2 + 0.1); - int binx_max = hPedXY->second->GetXaxis()->FindBin(padX + padSizeX / 2 - 0.1); - int biny_min = hPedXY->second->GetYaxis()->FindBin(padY - padSizeY / 2 + 0.1); - int biny_max = hPedXY->second->GetYaxis()->FindBin(padY + padSizeY / 2 - 0.1); - for (int by = biny_min; by <= biny_max; by++) { - for (int bx = binx_min; bx <= binx_max; bx++) { - hPedXY->second->SetBinContent(bx, by, mean); - } - } + hPedXY->second->Set(padX, padY, padSizeX, padSizeY, mean); } auto hNoiseXY = mHistogramNoiseXY[cathode].find(deId); if ((hNoiseXY != mHistogramNoiseXY[cathode].end()) && (hNoiseXY->second != NULL)) { - int binx_min = hNoiseXY->second->GetXaxis()->FindBin(padX - padSizeX / 2 + 0.1); - int binx_max = hNoiseXY->second->GetXaxis()->FindBin(padX + padSizeX / 2 - 0.1); - int biny_min = hNoiseXY->second->GetYaxis()->FindBin(padY - padSizeY / 2 + 0.1); - int biny_max = hNoiseXY->second->GetYaxis()->FindBin(padY + padSizeY / 2 - 0.1); - for (int by = biny_min; by <= biny_max; by++) { - for (int bx = binx_min; bx <= binx_max; bx++) { - hNoiseXY->second->SetBinContent(bx, by, rms); - } - } + hNoiseXY->second->Set(padX, padY, padSizeX, padSizeY, rms); } } diff --git a/Modules/MUON/MCH/src/PhysicsOccupancyCheck.cxx b/Modules/MUON/MCH/src/PhysicsOccupancyCheck.cxx new file mode 100644 index 0000000000..ddd11c4079 --- /dev/null +++ b/Modules/MUON/MCH/src/PhysicsOccupancyCheck.cxx @@ -0,0 +1,145 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file PhysicsOccupancyCheck.cxx +/// \author Andrea Ferrero, Sebastien Perrin +/// + +#include "MCHMappingInterface/Segmentation.h" +#include "MCHMappingSegContour/CathodeSegmentationContours.h" +#include "MCH/PhysicsOccupancyCheck.h" + +// ROOT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace o2::quality_control_modules::muonchambers +{ + +PhysicsOccupancyCheck::PhysicsOccupancyCheck() +{ + mPrintLevel = 1; + minOccupancy = 0.000000050; + maxOccupancy = 0.000000130; +} + +PhysicsOccupancyCheck::~PhysicsOccupancyCheck() {} + +void PhysicsOccupancyCheck::configure(std::string) +{ +} + +Quality PhysicsOccupancyCheck::check(std::map>* moMap) +{ + Quality result = Quality::Null; + + for (auto& [moName, mo] : *moMap) { + + (void)moName; + std::cout << mo->getName() << endl; + if (mo->getName().find("MeanOccupancyPerCycle") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + std::cout << mo->ClassName() << endl; + if (!h) { + return result; + } + + if (h->GetEntries() == 0) { + result = Quality::Medium; + } else { + int nbinsx = h->GetXaxis()->GetNbins(); + int nbad = 0; + for (int i = 1; i <= nbinsx; i++) { + Float_t occ = h->GetBinContent(i); + if (occ < minOccupancy || occ >= maxOccupancy) { + nbad += 1; + } + } + if (nbad < 1) { + result = Quality::Good; + std::cout << "GOOD" << endl; + } else { + result = Quality::Bad; + std::cout << "BAD" << endl; + } + } + } + } + return result; +} + +std::string PhysicsOccupancyCheck::getAcceptedType() { return "TH1"; } + +void PhysicsOccupancyCheck::beautify(std::shared_ptr mo, Quality checkResult) +{ + if (mo->getName().find("MeanOccupancyPerCycle") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + TPaveText* msg = new TPaveText(0.3, 0.9, 0.7, 0.95, "NDC"); + h->GetListOfFunctions()->Add(msg); + msg->SetName(Form("%s_msg", mo->GetName())); + + TLine* lmin = new TLine(0, minOccupancy, 1100, minOccupancy); + TLine* lmax = new TLine(0, maxOccupancy, 1100, maxOccupancy); + + h->GetListOfFunctions()->Add(lmin); + h->GetListOfFunctions()->Add(lmax); + + // lmin->Draw(); + // lmax->Draw(); + if (checkResult == Quality::Good) { + msg->Clear(); + msg->AddText("Occupancy consistently within limits: OK!!!"); + msg->SetFillColor(kGreen); + // + // h->SetFillColor(kGreen); + } else if (checkResult == Quality::Bad) { + LOG(INFO) << "Quality::Bad, setting to red"; + // + msg->Clear(); + msg->AddText("Call MCH on-call."); + msg->SetFillColor(kRed); + // + // h->SetFillColor(kRed); + } else if (checkResult == Quality::Medium) { + LOG(INFO) << "Quality::medium, setting to orange"; + // + msg->Clear(); + msg->AddText("No entries. If MCH in the run, check MCH TWiki"); + msg->SetFillColor(kYellow); + // h->SetFillColor(kOrange); + } + h->SetLineColor(kBlack); + + for (Int_t i = 1; i <= h->GetNbinsX(); i += 1) { + TBox* b = new TBox(h->GetBinLowEdge(i), + h->GetMinimum(), + h->GetBinWidth(i) + h->GetBinLowEdge(i), + h->GetBinContent(i)); + b->SetFillColor(kGreen); + if (h->GetBinContent(i) < minOccupancy || h->GetBinContent(i) >= maxOccupancy) { + b->SetFillColor(kRed); + } + h->GetListOfFunctions()->Add(b); + } + } +} + +} // namespace o2::quality_control_modules::muonchambers diff --git a/Modules/MUON/MCH/src/PhysicsPreclustersCheck.cxx b/Modules/MUON/MCH/src/PhysicsPreclustersCheck.cxx new file mode 100644 index 0000000000..aa6ef92084 --- /dev/null +++ b/Modules/MUON/MCH/src/PhysicsPreclustersCheck.cxx @@ -0,0 +1,495 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file PhysicsPreclustersCheck.cxx +/// \author Andrea Ferrero, Sebastien Perrin +/// + +#include "MCHMappingInterface/Segmentation.h" +#include "MCHMappingSegContour/CathodeSegmentationContours.h" +#include "MCH/PhysicsPreclustersCheck.h" + +// ROOT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace o2::quality_control_modules::muonchambers +{ + +PhysicsPreclustersCheck::PhysicsPreclustersCheck() +{ + mPrintLevel = 1; + minPseudoeff = 0.5; + maxPseudoeff = 1.0; + minMPV = 300; + maxMPV = 700; +} + +PhysicsPreclustersCheck::~PhysicsPreclustersCheck() {} + +void PhysicsPreclustersCheck::configure(std::string) +{ + // if (AliRecoParam::ConvertIndex(specie) == AliRecoParam::kCosmic) { + // minTOFrawTime = 150.; //ns + // maxTOFrawTime = 250.; //ns + // } +} + +Quality PhysicsPreclustersCheck::check(std::map>* moMap) +{ + // std::cout << "=================================" << std::endl; + // std::cout << "PhysicsOccupancyCheck::check() called" << std::endl; + // std::cout << "=================================" << std::endl; + Quality result = Quality::Null; + + for (auto& [moName, mo] : *moMap) { + + (void)moName; + // std::cout << mo->getName() <getName().find("QcMuonChambers_MeanPseudoeff_Mergeable_DoesGoodBHaveSomethingNB") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + std::cout << mo->ClassName() << endl; + if (!h) { + std::cout << "Pas trouvé l'objet" << std::endl; + return result; + } + + if (h->GetEntries() == 0) { + result = Quality::Medium; + } else { + int nbinsx = h->GetXaxis()->GetNbins(); + int nbad = 0; + for (int i = 1; i <= nbinsx; i++) { + Float_t occ = h->GetBinContent(i); + if (occ < minPseudoeff || occ > maxPseudoeff) { + nbad += 1; + } + } + if (nbad < 1) { + result = Quality::Good; + std::cout << "GOOD" << endl; + } else { + result = Quality::Bad; + std::cout << "BAD" << endl; + } + } + } + } + for (auto& [moName, mo] : *moMap) { + if (mo->getName().find("QcMuonChambers_MeanPseudoeff_Mergeable_DoesGoodNBHaveSomethingB") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + std::cout << mo->ClassName() << endl; + if (!h) { + std::cout << "Pas trouvé l'objet" << std::endl; + return result; + } + + if (h->GetEntries() == 0) { + result = Quality::Medium; + } else { + int nbinsx = h->GetXaxis()->GetNbins(); + int nbad = 0; + for (int i = 1; i <= nbinsx; i++) { + Float_t occ = h->GetBinContent(i); + if (occ < minPseudoeff || occ > maxPseudoeff) { + nbad += 1; + } + } + if (nbad < 1) { + result = Quality::Good; + std::cout << "GOOD" << endl; + } else { + result = Quality::Bad; + std::cout << "BAD" << endl; + } + } + } + } + + for (auto& [moName, mo] : *moMap) { + + (void)moName; + // std::cout << mo->getName() <getName().find("mMeanPseudoeffPerDE_DoesGoodBHaveSomethingNB_OnCycle") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + std::cout << mo->ClassName() << endl; + if (!h) { + std::cout << "Pas trouvé l'objet" << std::endl; + return result; + } + + if (h->GetEntries() == 0) { + result = Quality::Medium; + } else { + int nbinsx = h->GetXaxis()->GetNbins(); + int nbad = 0; + for (int i = 1; i <= nbinsx; i++) { + Float_t occ = h->GetBinContent(i); + if (occ < minPseudoeff || occ > maxPseudoeff) { + nbad += 1; + } + } + if (nbad < 1) { + result = Quality::Good; + std::cout << "GOOD" << endl; + } else { + result = Quality::Bad; + std::cout << "BAD" << endl; + } + } + } + } + + for (auto& [moName, mo] : *moMap) { + + (void)moName; + // std::cout << mo->getName() <getName().find("mMeanPseudoeffPerDE_DoesGoodNBHaveSomethingB_OnCycle") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + std::cout << mo->ClassName() << endl; + if (!h) { + std::cout << "Pas trouvé l'objet" << std::endl; + return result; + } + + if (h->GetEntries() == 0) { + result = Quality::Medium; + } else { + int nbinsx = h->GetXaxis()->GetNbins(); + int nbad = 0; + for (int i = 1; i <= nbinsx; i++) { + Float_t occ = h->GetBinContent(i); + if (occ < minPseudoeff || occ > maxPseudoeff) { + nbad += 1; + } + } + if (nbad < 1) { + result = Quality::Good; + std::cout << "GOOD" << endl; + } else { + result = Quality::Bad; + std::cout << "BAD" << endl; + } + } + } + } + + for (auto& [moName, mo] : *moMap) { + + (void)moName; + // std::cout << mo->getName() <getName().find("QcMuonChambers_MPV_Mergeable_OnCycle") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + std::cout << mo->ClassName() << endl; + if (!h) { + std::cout << "Pas trouvé l'objet" << std::endl; + return result; + } + + if (h->GetEntries() == 0) { + result = Quality::Medium; + } else { + int nbinsx = h->GetXaxis()->GetNbins(); + int nbad = 0; + for (int i = 1; i <= nbinsx; i++) { + Float_t occ = h->GetBinContent(i); + if (occ < minMPV || occ > maxMPV) { + nbad += 1; + } + } + if (nbad < 1) { + result = Quality::Good; + std::cout << "GOOD" << endl; + } else { + result = Quality::Bad; + std::cout << "BAD" << endl; + } + } + } + } + + return result; +} + +std::string PhysicsPreclustersCheck::getAcceptedType() { return "TH1"; } + +void PhysicsPreclustersCheck::beautify(std::shared_ptr mo, Quality checkResult) +{ + // std::cout<<"===================================="<getName().find("QcMuonChambers_MeanPseudoeff_Mergeable_DoesGoodBHaveSomethingNB") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + TPaveText* msg = new TPaveText(0.3, 0.9, 0.7, 0.95, "NDC"); + h->GetListOfFunctions()->Add(msg); + msg->SetName(Form("%s_msg", mo->GetName())); + + TLine* lmin = new TLine(0, minPseudoeff, 1100, minPseudoeff); + TLine* lmax = new TLine(0, maxPseudoeff, 1100, maxPseudoeff); + + h->GetListOfFunctions()->Add(lmin); + h->GetListOfFunctions()->Add(lmax); + + // lmin->Draw(); + // lmax->Draw(); + if (checkResult == Quality::Good) { + msg->Clear(); + msg->AddText("Pseudo-efficiency consistently within limits: OK!!!"); + msg->SetFillColor(kGreen); + // + // h->SetFillColor(kGreen); + } else if (checkResult == Quality::Bad) { + LOG(INFO) << "Quality::Bad, setting to red"; + // + msg->Clear(); + msg->AddText("Call MCH on-call."); + msg->SetFillColor(kRed); + // + // h->SetFillColor(kRed); + } else if (checkResult == Quality::Medium) { + LOG(INFO) << "Quality::medium, setting to orange"; + // + msg->Clear(); + msg->AddText("No entries. If MCH in the run, check MCH TWiki"); + msg->SetFillColor(kYellow); + // h->SetFillColor(kOrange); + } + h->SetLineColor(kBlack); + + for (Int_t i = 1; i <= h->GetNbinsX(); i += 1) { + TBox* b = new TBox(h->GetBinLowEdge(i), + h->GetMinimum(), + h->GetBinWidth(i) + h->GetBinLowEdge(i), + h->GetBinContent(i)); + b->SetFillColor(kGreen); + if (h->GetBinContent(i) < minPseudoeff || h->GetBinContent(i) > maxPseudoeff) { + b->SetFillColor(kRed); + } + h->GetListOfFunctions()->Add(b); + } + } + + if (mo->getName().find("QcMuonChambers_MeanPseudoeff_Mergeable_DoesGoodNBHaveSomethingB") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + TPaveText* msg = new TPaveText(0.3, 0.9, 0.7, 0.95, "NDC"); + h->GetListOfFunctions()->Add(msg); + msg->SetName(Form("%s_msg", mo->GetName())); + + TLine* lmin = new TLine(0, minPseudoeff, 1100, minPseudoeff); + TLine* lmax = new TLine(0, maxPseudoeff, 1100, maxPseudoeff); + + h->GetListOfFunctions()->Add(lmin); + h->GetListOfFunctions()->Add(lmax); + + // lmin->Draw(); + // lmax->Draw(); + if (checkResult == Quality::Good) { + msg->Clear(); + msg->AddText("Pseudo-efficiency consistently within limits: OK!!!"); + msg->SetFillColor(kGreen); + // + // h->SetFillColor(kGreen); + } else if (checkResult == Quality::Bad) { + LOG(INFO) << "Quality::Bad, setting to red"; + // + msg->Clear(); + msg->AddText("Call MCH on-call."); + msg->SetFillColor(kRed); + // + // h->SetFillColor(kRed); + } else if (checkResult == Quality::Medium) { + LOG(INFO) << "Quality::medium, setting to orange"; + // + msg->Clear(); + msg->AddText("No entries. If MCH in the run, check MCH TWiki"); + msg->SetFillColor(kYellow); + // h->SetFillColor(kOrange); + } + h->SetLineColor(kBlack); + + for (Int_t i = 1; i <= h->GetNbinsX(); i += 1) { + TBox* b = new TBox(h->GetBinLowEdge(i), + h->GetMinimum(), + h->GetBinWidth(i) + h->GetBinLowEdge(i), + h->GetBinContent(i)); + b->SetFillColor(kGreen); + if (h->GetBinContent(i) < minPseudoeff || h->GetBinContent(i) > maxPseudoeff) { + b->SetFillColor(kRed); + } + h->GetListOfFunctions()->Add(b); + } + } + + if (mo->getName().find("mMeanPseudoeffPerDE_DoesGoodBHaveSomethingNB_OnCycle") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + TPaveText* msg = new TPaveText(0.3, 0.9, 0.7, 0.95, "NDC"); + h->GetListOfFunctions()->Add(msg); + msg->SetName(Form("%s_msg", mo->GetName())); + + TLine* lmin = new TLine(0, minPseudoeff, 1100, minPseudoeff); + TLine* lmax = new TLine(0, maxPseudoeff, 1100, maxPseudoeff); + + h->GetListOfFunctions()->Add(lmin); + h->GetListOfFunctions()->Add(lmax); + + // lmin->Draw(); + // lmax->Draw(); + if (checkResult == Quality::Good) { + msg->Clear(); + msg->AddText("Pseudo-efficiency consistently within limits: OK!!!"); + msg->SetFillColor(kGreen); + // + // h->SetFillColor(kGreen); + } else if (checkResult == Quality::Bad) { + LOG(INFO) << "Quality::Bad, setting to red"; + // + msg->Clear(); + msg->AddText("Call MCH on-call."); + msg->SetFillColor(kRed); + // + // h->SetFillColor(kRed); + } else if (checkResult == Quality::Medium) { + LOG(INFO) << "Quality::medium, setting to orange"; + // + msg->Clear(); + msg->AddText("No entries. If MCH in the run, check MCH TWiki"); + msg->SetFillColor(kYellow); + // h->SetFillColor(kOrange); + } + h->SetLineColor(kBlack); + + for (Int_t i = 1; i <= h->GetNbinsX(); i += 1) { + TBox* b = new TBox(h->GetBinLowEdge(i), + h->GetMinimum(), + h->GetBinWidth(i) + h->GetBinLowEdge(i), + h->GetBinContent(i)); + b->SetFillColor(kGreen); + if (h->GetBinContent(i) < minPseudoeff || h->GetBinContent(i) > maxPseudoeff) { + b->SetFillColor(kRed); + } + h->GetListOfFunctions()->Add(b); + } + } + + if (mo->getName().find("mMeanPseudoeffPerDE_DoesGoodNBHaveSomethingB_OnCycle") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + TPaveText* msg = new TPaveText(0.3, 0.9, 0.7, 0.95, "NDC"); + h->GetListOfFunctions()->Add(msg); + msg->SetName(Form("%s_msg", mo->GetName())); + + TLine* lmin = new TLine(0, minPseudoeff, 1100, minPseudoeff); + TLine* lmax = new TLine(0, maxPseudoeff, 1100, maxPseudoeff); + + h->GetListOfFunctions()->Add(lmin); + h->GetListOfFunctions()->Add(lmax); + + // lmin->Draw(); + // lmax->Draw(); + if (checkResult == Quality::Good) { + msg->Clear(); + msg->AddText("Pseudo-efficiency consistently within limits: OK!!!"); + msg->SetFillColor(kGreen); + // + // h->SetFillColor(kGreen); + } else if (checkResult == Quality::Bad) { + LOG(INFO) << "Quality::Bad, setting to red"; + // + msg->Clear(); + msg->AddText("Call MCH on-call."); + msg->SetFillColor(kRed); + // + // h->SetFillColor(kRed); + } else if (checkResult == Quality::Medium) { + LOG(INFO) << "Quality::medium, setting to orange"; + // + msg->Clear(); + msg->AddText("No entries. If MCH in the run, check MCH TWiki"); + msg->SetFillColor(kYellow); + // h->SetFillColor(kOrange); + } + h->SetLineColor(kBlack); + + for (Int_t i = 1; i <= h->GetNbinsX(); i += 1) { + TBox* b = new TBox(h->GetBinLowEdge(i), + h->GetMinimum(), + h->GetBinWidth(i) + h->GetBinLowEdge(i), + h->GetBinContent(i)); + b->SetFillColor(kGreen); + if (h->GetBinContent(i) < minPseudoeff || h->GetBinContent(i) > maxPseudoeff) { + b->SetFillColor(kRed); + } + h->GetListOfFunctions()->Add(b); + } + } + + if (mo->getName().find("QcMuonChambers_MPV_Mergeable_OnCycle") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + TPaveText* msg = new TPaveText(0.3, 0.9, 0.7, 0.95, "NDC"); + h->GetListOfFunctions()->Add(msg); + msg->SetName(Form("%s_msg", mo->GetName())); + + TLine* lmin = new TLine(0, minMPV, 1100, minMPV); + TLine* lmax = new TLine(0, maxMPV, 1100, maxMPV); + + h->GetListOfFunctions()->Add(lmin); + h->GetListOfFunctions()->Add(lmax); + + // lmin->Draw(); + // lmax->Draw(); + if (checkResult == Quality::Good) { + msg->Clear(); + msg->AddText("MPV consistently within limits: OK!!!"); + msg->SetFillColor(kGreen); + // + // h->SetFillColor(kGreen); + } else if (checkResult == Quality::Bad) { + LOG(INFO) << "Quality::Bad, setting to red"; + // + msg->Clear(); + msg->AddText("Call MCH on-call."); + msg->SetFillColor(kRed); + // + // h->SetFillColor(kRed); + } else if (checkResult == Quality::Medium) { + LOG(INFO) << "Quality::medium, setting to orange"; + // + msg->Clear(); + msg->AddText("No entries. If MCH in the run, check MCH TWiki"); + msg->SetFillColor(kYellow); + // h->SetFillColor(kOrange); + } + h->SetLineColor(kBlack); + + for (Int_t i = 1; i <= h->GetNbinsX(); i += 1) { + TBox* b = new TBox(h->GetBinLowEdge(i), + h->GetMinimum(), + h->GetBinWidth(i) + h->GetBinLowEdge(i), + h->GetBinContent(i)); + b->SetFillColor(kGreen); + if (h->GetBinContent(i) < minMPV || h->GetBinContent(i) >= maxMPV) { + b->SetFillColor(kRed); + } + h->GetListOfFunctions()->Add(b); + } + } +} + +} // namespace o2::quality_control_modules::muonchambers diff --git a/Modules/MUON/MCH/src/PhysicsTaskDigits.cxx b/Modules/MUON/MCH/src/PhysicsTaskDigits.cxx index 49ec56025c..3c5366849b 100644 --- a/Modules/MUON/MCH/src/PhysicsTaskDigits.cxx +++ b/Modules/MUON/MCH/src/PhysicsTaskDigits.cxx @@ -49,11 +49,6 @@ PhysicsTaskDigits::PhysicsTaskDigits() : TaskInterface() {} PhysicsTaskDigits::~PhysicsTaskDigits() {} -static std::string getHistoPath(int deId) -{ - return fmt::format("ST{}/DE{}/", (deId - 100) / 200 + 1, deId); -} - void PhysicsTaskDigits::initialize(o2::framework::InitContext& /*ctx*/) { QcInfoLogger::GetInstance() << "initialize PhysicsTaskDigits" << AliceO2::InfoLogger::InfoLogger::endm; @@ -91,6 +86,11 @@ void PhysicsTaskDigits::initialize(o2::framework::InitContext& /*ctx*/) getObjectsManager()->startPublishing(mHistogramOccupancyElec); mHistogramOccupancyElec->SetOption("colz"); + mMeanOccupancyPerDE = new MergeableTH1OccupancyPerDE("MeanOccupancy", "Mean Occupancy of each DE (KHz)", mHistogramNHitsElec, mHistogramNorbitsElec); + getObjectsManager()->startPublishing(mMeanOccupancyPerDE); + mMeanOccupancyPerDECycle = new MergeableTH1OccupancyPerDECycle("MeanOccupancyPerCycle", "Mean Occupancy of each DE Per Cycle (MHz)", mHistogramNHitsElec, mHistogramNorbitsElec); + getObjectsManager()->startPublishing(mMeanOccupancyPerDECycle); + // Histograms in detector coordinates for (auto de : o2::mch::raw::deIdsForAllMCH) { TH1F* h = new TH1F(TString::Format("%sADCamplitude_DE%03d", getHistoPath(de).c_str(), de), @@ -98,24 +98,19 @@ void PhysicsTaskDigits::initialize(o2::framework::InitContext& /*ctx*/) mHistogramADCamplitudeDE.insert(make_pair(de, h)); getObjectsManager()->startPublishing(h); - float Xsize = 40 * 5; - float Xsize2 = Xsize / 2; - float Ysize = 50; - float Ysize2 = Ysize / 2; - - TH2F* h2n0 = new TH2F(TString::Format("%sNhits_DE%03d_B", getHistoPath(de).c_str(), de), - TString::Format("Number of hits (DE%03d B)", de), Xsize * 2, -Xsize2, Xsize2, Ysize * 2, -Ysize2, Ysize2); + DetectorHistogram* h2n0 = new DetectorHistogram(TString::Format("%sNhits_DE%03d_B", getHistoPath(de).c_str(), de), + TString::Format("Number of hits (DE%03d B)", de), de); mHistogramNhitsDE[0].insert(make_pair(de, h2n0)); - TH2F* h2n1 = new TH2F(TString::Format("%sNhits_DE%03d_NB", getHistoPath(de).c_str(), de), - TString::Format("Number of hits (DE%03d NB)", de), Xsize * 2, -Xsize2, Xsize2, Ysize * 2, -Ysize2, Ysize2); + DetectorHistogram* h2n1 = new DetectorHistogram(TString::Format("%sNhits_DE%03d_NB", getHistoPath(de).c_str(), de), + TString::Format("Number of hits (DE%03d NB)", de), de); mHistogramNhitsDE[1].insert(make_pair(de, h2n1)); - TH2F* h2d0 = new TH2F(TString::Format("%sNorbits_DE%03d_B", getHistoPath(de).c_str(), de), - TString::Format("Number of orbits (DE%03d B)", de), Xsize * 2, -Xsize2, Xsize2, Ysize * 2, -Ysize2, Ysize2); + DetectorHistogram* h2d0 = new DetectorHistogram(TString::Format("%sNorbits_DE%03d_B", getHistoPath(de).c_str(), de), + TString::Format("Number of orbits (DE%03d B)", de), de); mHistogramNorbitsDE[0].insert(make_pair(de, h2d0)); - TH2F* h2d1 = new TH2F(TString::Format("%sNorbits_DE%03d_NB", getHistoPath(de).c_str(), de), - TString::Format("Number of orbits (DE%03d NB)", de), Xsize * 2, -Xsize2, Xsize2, Ysize * 2, -Ysize2, Ysize2); + DetectorHistogram* h2d1 = new DetectorHistogram(TString::Format("%sNorbits_DE%03d_NB", getHistoPath(de).c_str(), de), + TString::Format("Number of orbits (DE%03d NB)", de), de); mHistogramNorbitsDE[1].insert(make_pair(de, h2d1)); MergeableTH2Ratio* hm = new MergeableTH2Ratio(TString::Format("%sOccupancy_B_XY_%03d", getHistoPath(de).c_str(), de), @@ -227,17 +222,7 @@ void PhysicsTaskDigits::plotDigit(const o2::mch::Digit& digit) // Fill X Y 2D hits histogram with fired pads distribution auto h2 = mHistogramNhitsDE[cathode].find(de); if ((h2 != mHistogramNhitsDE[cathode].end()) && (h2->second != NULL)) { - int binx_min = h2->second->GetXaxis()->FindBin(padX - padSizeX / 2 + 0.1); - int binx_max = h2->second->GetXaxis()->FindBin(padX + padSizeX / 2 - 0.1); - int biny_min = h2->second->GetYaxis()->FindBin(padY - padSizeY / 2 + 0.1); - int biny_max = h2->second->GetYaxis()->FindBin(padY + padSizeY / 2 - 0.1); - for (int by = biny_min; by <= biny_max; by++) { - float y = h2->second->GetYaxis()->GetBinCenter(by); - for (int bx = binx_min; bx <= binx_max; bx++) { - float x = h2->second->GetXaxis()->GetBinCenter(bx); - h2->second->Fill(x, y); - } - } + h2->second->Fill(padX, padY, padSizeX, padSizeY); } // Using the mapping to go from Digit info (de, pad) to Elec info (fee, link) and fill Elec Histogram, @@ -306,24 +291,15 @@ void PhysicsTaskDigits::updateOrbits() int ybin = channel + 1; mHistogramNorbitsElec->SetBinContent(xbin, ybin, mNOrbits[feeId][linkId]); - double x_pad = segment.padPositionX(padid); - double y_pad = segment.padPositionY(padid); + double padX = segment.padPositionX(padid); + double padY = segment.padPositionY(padid); float padSizeX = segment.padSizeX(padid); float padSizeY = segment.padSizeY(padid); int cathode = segment.isBendingPad(padid) ? 0 : 1; auto h2 = mHistogramNorbitsDE[cathode].find(de); if ((h2 != mHistogramNorbitsDE[cathode].end()) && (h2->second != NULL)) { - - int binx_min = h2->second->GetXaxis()->FindBin(x_pad - padSizeX / 2 + 0.1); - int binx_max = h2->second->GetXaxis()->FindBin(x_pad + padSizeX / 2 - 0.1); - int biny_min = h2->second->GetYaxis()->FindBin(y_pad - padSizeY / 2 + 0.1); - int biny_max = h2->second->GetYaxis()->FindBin(y_pad + padSizeY / 2 - 0.1); - for (int by = biny_min; by <= biny_max; by++) { - for (int bx = binx_min; bx <= binx_max; bx++) { - h2->second->SetBinContent(bx, by, mNOrbits[feeId][linkId]); - } - } + h2->second->Set(padX, padY, padSizeX, padSizeY, mNOrbits[feeId][linkId]); } } } @@ -351,6 +327,9 @@ void PhysicsTaskDigits::endOfCycle() } } } + + mMeanOccupancyPerDE->update(); + mMeanOccupancyPerDECycle->update(); } void PhysicsTaskDigits::endOfActivity(Activity& /*activity*/) @@ -358,13 +337,15 @@ void PhysicsTaskDigits::endOfActivity(Activity& /*activity*/) QcInfoLogger::GetInstance() << "endOfActivity" << AliceO2::InfoLogger::InfoLogger::endm; #ifdef QC_MCH_SAVE_TEMP_ROOTFILE - TFile f("qc-digits.root", "RECREATE"); + TFile f("mch-qc-digits.root", "RECREATE"); mHistogramNorbitsElec->Write(); mHistogramNHitsElec->Write(); mHistogramOccupancyElec->Write(); + mMeanOccupancyPerDE->Write(); + mMeanOccupancyPerDECycle->Write(); - for (int de = 0; de < 1100; de++) { + for (auto de : o2::mch::raw::deIdsForAllMCH) { { auto h = mHistogramADCamplitudeDE.find(de); if ((h != mHistogramADCamplitudeDE.end()) && (h->second != NULL)) { @@ -400,7 +381,6 @@ void PhysicsTaskDigits::endOfActivity(Activity& /*activity*/) void PhysicsTaskDigits::reset() { // clean all the monitor objects here - QcInfoLogger::GetInstance() << "Reseting the histogram" << AliceO2::InfoLogger::InfoLogger::endm; } diff --git a/Modules/MUON/MCH/src/PhysicsTaskPreclusters.cxx b/Modules/MUON/MCH/src/PhysicsTaskPreclusters.cxx index 315947af87..84413643ed 100644 --- a/Modules/MUON/MCH/src/PhysicsTaskPreclusters.cxx +++ b/Modules/MUON/MCH/src/PhysicsTaskPreclusters.cxx @@ -39,7 +39,7 @@ using namespace std; using namespace o2::mch::raw; using namespace o2::quality_control::core; -// #define QC_MCH_SAVE_TEMP_ROOTFILE 1 +//#define QC_MCH_SAVE_TEMP_ROOTFILE 1 namespace o2 { @@ -55,70 +55,85 @@ void PhysicsTaskPreclusters::initialize(o2::framework::InitContext& /*ctx*/) { QcInfoLogger::GetInstance() << "initialize PhysicsTaskPreclusters" << AliceO2::InfoLogger::InfoLogger::endm; - for (int de = 0; de < 1100; de++) { - MeanPseudoeffDE[de] = MeanPseudoeffDECycle[de] = LastPreclBNBDE[de] = NewPreclBNBDE[de] = LastPreclNumDE[de] = NewPreclNumDE[de] = 0; - } - - // 1D histograms for mean pseudoeff per DE (integrated or per elapsed cycle) - Used in trending - mMeanPseudoeffPerDE = new TH1F("QcMuonChambers_MeanPseudoeff", "Mean Pseudoeff of each DE", 1100, -0.5, 1099.5); - getObjectsManager()->startPublishing(mMeanPseudoeffPerDE); - mMeanPseudoeffPerDECycle = new TH1F("QcMuonChambers_MeanPseudoeff_OnCycle", "Mean Pseudoeff of each DE during the cycle", 1100, -0.5, 1099.5); - getObjectsManager()->startPublishing(mMeanPseudoeffPerDECycle); - for (auto de : o2::mch::raw::deIdsForAllMCH) { - TH1F* h = new TH1F(TString::Format("QcMuonChambers_Cluster_Charge_DE%03d", de), - TString::Format("QcMuonChambers - cluster charge (DE%03d)", de), 1000, 0, 50000); + TH2F* h = new TH2F(TString::Format("%sCluster_Charge_DE%03d", getHistoPath(de).c_str(), de), + TString::Format("Cluster charge (DE%03d)", de), 1000, 0, 50000, 4, 0, 4); + h->GetYaxis()->SetBinLabel(1, "#splitline{ nB <= 1}{nNB <= 1}"); + h->GetYaxis()->SetBinLabel(2, "#splitline{ nB >= 2}{nNB <= 1}"); + h->GetYaxis()->SetBinLabel(3, "#splitline{ nB <= 1}{nNB >= 2}"); + h->GetYaxis()->SetBinLabel(4, "#splitline{ nB >= 2}{nNB >= 2}"); mHistogramClchgDE.insert(make_pair(de, h)); - h = new TH1F(TString::Format("QcMuonChambers_Cluster_Charge_OnCycle_DE%03d", de), - TString::Format("QcMuonChambers - cluster charge on cycle (DE%03d)", de), 1000, 0, 50000); - mHistogramClchgDEOnCycle.insert(make_pair(de, h)); - - float Xsize = 40 * 5; - float Xsize2 = Xsize / 2; - float Ysize = 50; - float Ysize2 = Ysize / 2; - float scale = 0.5; + getObjectsManager()->startPublishing(h); + TH1F* h1 = new TH1F(TString::Format("%sCluster_Charge_OnCycle_DE%03d", getHistoPath(de).c_str(), de), + TString::Format("Cluster charge on cycle (DE%03d)", de), 1000, 0, 50000); + mHistogramClchgDEOnCycle.insert(make_pair(de, h1)); + + h = new TH2F(TString::Format("%sCluster_Size_DE%03d", getHistoPath(de).c_str(), de), + TString::Format("Cluster size (DE%03d)", de), 10, 0, 10, 3, 0, 3); + h->GetYaxis()->SetBinLabel(1, "B"); + h->GetYaxis()->SetBinLabel(2, "NB"); + h->GetYaxis()->SetBinLabel(3, "B+NB"); + mHistogramClsizeDE.insert(make_pair(de, h)); + getObjectsManager()->startPublishing(h); // Histograms using the XY Mapping { - TH2F* hXY = new TH2F(TString::Format("QcMuonChambers_Preclusters_Number_XY_%03d", de), - TString::Format("QcMuonChambers - Preclusters Number XY (DE%03d B)", de), Xsize / scale, -Xsize2, Xsize2, Ysize / scale, -Ysize2, Ysize2); - mHistogramPreclustersXY[0].insert(make_pair(de, hXY)); - hXY = new TH2F(TString::Format("QcMuonChambers_Preclusters_B_XY_%03d", de), - TString::Format("QcMuonChambers - Preclusters XY (DE%03d B)", de), Xsize / scale, -Xsize2, Xsize2, Ysize / scale, -Ysize2, Ysize2); - mHistogramPreclustersXY[1].insert(make_pair(de, hXY)); - hXY = new TH2F(TString::Format("QcMuonChambers_Preclusters_NB_XY_%03d", de), - TString::Format("QcMuonChambers - Preclusters XY (DE%03d NB)", de), Xsize / scale, -Xsize2, Xsize2, Ysize / scale, -Ysize2, Ysize2); - mHistogramPreclustersXY[2].insert(make_pair(de, hXY)); - hXY = new TH2F(TString::Format("QcMuonChambers_Preclusters_BNB_XY_%03d", de), - TString::Format("QcMuonChambers - Preclusters XY (DE%03d B+NB)", de), Xsize / scale, -Xsize2, Xsize2, Ysize / scale, -Ysize2, Ysize2); - mHistogramPreclustersXY[3].insert(make_pair(de, hXY)); - hXY = new TH2F(TString::Format("QcMuonChambers_Pseudoeff_B_XY_%03d", de), - TString::Format("QcMuonChambers - Pseudo-efficiency XY (DE%03d B)", de), Xsize / scale, -Xsize2, Xsize2, Ysize / scale, -Ysize2, Ysize2); - mHistogramPseudoeffXY[0].insert(make_pair(de, hXY)); - hXY = new TH2F(TString::Format("QcMuonChambers_Pseudoeff_NB_XY_%03d", de), - TString::Format("QcMuonChambers - Pseudo-efficiency XY (DE%03d NB)", de), Xsize / scale, -Xsize2, Xsize2, Ysize / scale, -Ysize2, Ysize2); - mHistogramPseudoeffXY[1].insert(make_pair(de, hXY)); - hXY = new TH2F(TString::Format("QcMuonChambers_Pseudoeff_BNB_XY_%03d", de), - TString::Format("QcMuonChambers - Pseudo-efficiency XY (DE%03d B+NB)", de), Xsize / scale, -Xsize2, Xsize2, Ysize / scale, -Ysize2, Ysize2); - mHistogramPseudoeffXY[2].insert(make_pair(de, hXY)); + DetectorHistogram* hXY0 = new DetectorHistogram(TString::Format("%sPreclusters_NBgood_XY_%03d", getHistoPath(de).c_str(), de), + TString::Format("Preclusters XY (DE%03d NB, good)", de), de); + mHistogramPreclustersXY[0].insert(make_pair(de, hXY0)); + DetectorHistogram* hXY1 = new DetectorHistogram(TString::Format("%sPreclusters_Bgood_XY_%03d", getHistoPath(de).c_str(), de), + TString::Format("Preclusters XY (DE%03d B, good)", de), de); + mHistogramPreclustersXY[1].insert(make_pair(de, hXY1)); + DetectorHistogram* hXY2 = new DetectorHistogram(TString::Format("%sPreclustersNBgoodAndSomethingB_XY_%03d", getHistoPath(de).c_str(), de), + TString::Format("Preclusters XY (DE%03d B)", de), de); + mHistogramPreclustersXY[2].insert(make_pair(de, hXY2)); + DetectorHistogram* hXY3 = new DetectorHistogram(TString::Format("%sPreclustersBgoodAndSomethingNB_XY_%03d", getHistoPath(de).c_str(), de), + TString::Format("Preclusters XY (DE%03d NB)", de), de); + mHistogramPreclustersXY[3].insert(make_pair(de, hXY3)); + + MergeableTH2Ratio* hXYPseudo0 = new MergeableTH2Ratio(TString::Format("%sPseudoeff_B_XY_%03d", getHistoPath(de).c_str(), de), + TString::Format("Pseudo-efficiency XY (DE%03d B)", de), + hXY2, hXY0); + mHistogramPseudoeffXY[0].insert(make_pair(de, hXYPseudo0)); + getObjectsManager()->startPublishing(hXYPseudo0); + + MergeableTH2Ratio* hXYPseudo1 = new MergeableTH2Ratio(TString::Format("%sPseudoeff_NB_XY_%03d", getHistoPath(de).c_str(), de), + TString::Format("Pseudo-efficiency XY (DE%03d NB)", de), + hXY3, hXY1); + mHistogramPseudoeffXY[1].insert(make_pair(de, hXYPseudo1)); + getObjectsManager()->startPublishing(hXYPseudo1); } } - mHistogramPseudoeff[0] = new GlobalHistogram("QcMuonChambers_Pseudoeff_den", "Pseudo-efficiency cluster total count"); - mHistogramPseudoeff[0]->init(); - mHistogramPseudoeff[0]->SetOption("colz"); - getObjectsManager()->startPublishing(mHistogramPseudoeff[0]); - mHistogramPseudoeff[1] = new GlobalHistogram("QcMuonChambers_Pseudoeff", "Pseudo-efficiency - Clusters on B or NB"); - mHistogramPseudoeff[1]->init(); - mHistogramPseudoeff[1]->SetOption("colz"); - getObjectsManager()->startPublishing(mHistogramPseudoeff[1]); - mHistogramPseudoeff[2] = new GlobalHistogram("QcMuonChambers_Pseudoeff_BNB", "Pseudo-efficiency - Clusters on B and NB"); - mHistogramPseudoeff[2]->init(); - mHistogramPseudoeff[2]->SetOption("colz"); - getObjectsManager()->startPublishing(mHistogramPseudoeff[2]); + mHistogramPseudoeff_NumsAndDens[0] = new GlobalHistogram("Pseudoeff_den_Mergeable", "Count - Good clusters"); + mHistogramPseudoeff_NumsAndDens[0]->init(); + mHistogramPseudoeff_NumsAndDens[0]->SetOption("colz"); + getObjectsManager()->startPublishing(mHistogramPseudoeff_NumsAndDens[0]); + mHistogramPseudoeff_NumsAndDens[1] = new GlobalHistogram("Pseudoeff_num_Mergeable", "Count - Good clusters associated to something on the other cathode"); + mHistogramPseudoeff_NumsAndDens[1]->init(); + mHistogramPseudoeff_NumsAndDens[1]->SetOption("colz"); + getObjectsManager()->startPublishing(mHistogramPseudoeff_NumsAndDens[1]); + + mHistogramPseudoeff = new MergeableTH2Ratio("Pseudoeff_Mergeable", "Pseudo-efficiency - Good clusters with something on other side/Good clusters", + mHistogramPseudoeff_NumsAndDens[1], mHistogramPseudoeff_NumsAndDens[0]); + getObjectsManager()->startPublishing(mHistogramPseudoeff); + mHistogramPseudoeff->SetOption("colz"); + + // 1D histograms for mean pseudoeff per DE (integrated or per elapsed cycle) - Used in trending + mMeanPseudoeffPerDE_DoesGoodNBHaveSomethingB = new MergeableTH1PseudoEfficiencyPerDE("MeanPseudoeff_Mergeable_DoesGoodNBHaveSomethingB", "Mean Pseudoeff of each DE (Good clusters on NB associated with something on B)", mHistogramPreclustersXY[3], mHistogramPreclustersXY[1]); + getObjectsManager()->startPublishing(mMeanPseudoeffPerDE_DoesGoodNBHaveSomethingB); + mMeanPseudoeffPerDE_DoesGoodBHaveSomethingNB = new MergeableTH1PseudoEfficiencyPerDE("MeanPseudoeff_Mergeable_DoesGoodBHaveSomethingNB", "Mean Pseudoeff of each DE (Good clusters on B associated with something on NB)", mHistogramPreclustersXY[2], mHistogramPreclustersXY[0]); + getObjectsManager()->startPublishing(mMeanPseudoeffPerDE_DoesGoodBHaveSomethingNB); + + mMeanPseudoeffPerDE_DoesGoodNBHaveSomethingB_Cycle = new MergeableTH1PseudoEfficiencyPerDECycle("MeanPseudoeffPerDE_DoesGoodNBHaveSomethingB_OnCycle", "Mean Pseudoeff of each DE during the cycle (Good clusters on NB associated with something on B)", mHistogramPreclustersXY[3], mHistogramPreclustersXY[1]); + getObjectsManager()->startPublishing(mMeanPseudoeffPerDE_DoesGoodNBHaveSomethingB_Cycle); + mMeanPseudoeffPerDE_DoesGoodBHaveSomethingNB_Cycle = new MergeableTH1PseudoEfficiencyPerDECycle("MeanPseudoeffPerDE_DoesGoodBHaveSomethingNB_OnCycle", "Mean Pseudoeff of each DE during the cycle (Good clusters on B associated with something on NB)", mHistogramPreclustersXY[2], mHistogramPreclustersXY[0]); + getObjectsManager()->startPublishing(mMeanPseudoeffPerDE_DoesGoodBHaveSomethingNB_Cycle); + + mMPVCycle = new MergeableTH1MPVPerDECycle("MPV_Mergeable_OnCycle", "MPV of each DE cluster charge during the cycle", mHistogramClchgDEOnCycle); + getObjectsManager()->startPublishing(mMPVCycle); } void PhysicsTaskPreclusters::startOfActivity(Activity& /*activity*/) @@ -133,6 +148,7 @@ void PhysicsTaskPreclusters::startOfCycle() void PhysicsTaskPreclusters::monitorData(o2::framework::ProcessingContext& ctx) { + bool verbose = false; // get the input preclusters and associated digits auto preClusters = ctx.inputs().get>("preclusters"); auto digits = ctx.inputs().get>("preclusterdigits"); @@ -144,7 +160,7 @@ void PhysicsTaskPreclusters::monitorData(o2::framework::ProcessingContext& ctx) } } - if (print) { + if (print && verbose) { printPreclusters(preClusters, digits); } } @@ -160,8 +176,6 @@ static void CoG(gsl::span precluster, double& Xcog, double double ymax = -1E9; double charge[] = { 0.0, 0.0 }; int multiplicity[] = { 0, 0 }; - double padXPos[] = { 0, 0 }; - double padYPos[] = { 0, 0 }; isWide[0] = isWide[1] = false; // isWide tells if a given precluster is extended enough on a given cathode. On the bending side for exemple, a wide precluster would have at least 2 pads fired in the x direction (so when clustering it, we obtain a meaningful value for x). If a precluster is not wide and on a single cathode, when clustering, one of the coordinates will not be computed properly and set to the center of the pad by default. @@ -171,10 +185,13 @@ static void CoG(gsl::span precluster, double& Xcog, double double xsize[] = { 0.0, 0.0 }; double ysize[] = { 0.0, 0.0 }; + std::set padPos[2]; + int detid = precluster[0].getDetID(); const o2::mch::mapping::Segmentation& segment = o2::mch::mapping::segmentation(detid); - for (const o2::mch::Digit& digit : precluster) { + for (ssize_t i = 0; (unsigned)i < precluster.size(); ++i) { + const o2::mch::Digit& digit = precluster[i]; int padid = digit.getPadID(); // position and size of current pad @@ -197,22 +214,10 @@ static void CoG(gsl::span precluster, double& Xcog, double ysize[cathode] += padSize[1]; charge[cathode] += digit.getADC(); - if (multiplicity[cathode] == 0) { - if (cathode == 0) { - padXPos[0] = padPosition[0]; - padYPos[0] = padPosition[1]; - } - if (cathode == 1) { - padXPos[1] = padPosition[0]; - padYPos[1] = padPosition[1]; - } - } else if (multiplicity[cathode] > 0) { - if ((cathode == 0) && (padXPos[0] != padPosition[0])) { - isWide[0] = true; - } - if ((cathode == 1) && (padYPos[1] != padPosition[1])) { - isWide[1] = true; - } + if (cathode == 0) { + padPos[0].insert(padPosition[1]); + } else if (cathode == 1) { + padPos[1].insert(padPosition[0]); } multiplicity[cathode] += 1; @@ -234,6 +239,9 @@ static void CoG(gsl::span precluster, double& Xcog, double } } + isWide[0] = (padPos[0].size() > 1); + isWide[1] = (padPos[1].size() > 1); + // each CoG coordinate is taken from the cathode with the best precision Xcog = (xsize[0] < xsize[1]) ? x[0] : x[1]; Ycog = (ysize[0] < ysize[1]) ? y[0] : y[1]; @@ -250,13 +258,19 @@ bool PhysicsTaskPreclusters::plotPrecluster(const o2::mch::PreCluster& preCluste // get the digits of this precluster auto preClusterDigits = digits.subspan(preCluster.firstDigit, preCluster.nDigits); + // whether a cathode has digits or not bool cathode[2] = { false, false }; + // total charge on each cathode float chargeSum[2] = { 0, 0 }; + // largest signal in each cathode float chargeMax[2] = { 0, 0 }; + // number of digits in each cathode + int multiplicity[2] = { 0, 0 }; int detid = preClusterDigits[0].getDetID(); const o2::mch::mapping::Segmentation& segment = o2::mch::mapping::segmentation(detid); + // loop over digits and collect information on charge and multiplicity for (const o2::mch::Digit& digit : preClusterDigits) { int padid = digit.getPadID(); @@ -264,116 +278,153 @@ bool PhysicsTaskPreclusters::plotPrecluster(const o2::mch::PreCluster& preCluste int cid = segment.isBendingPad(padid) ? 0 : 1; cathode[cid] = true; chargeSum[cid] += digit.getADC(); + multiplicity[cid] += 1; if (digit.getADC() > chargeMax[cid]) { chargeMax[cid] = digit.getADC(); } } - float chargeTot = chargeSum[0] + chargeSum[1]; - auto hCharge = mHistogramClchgDE.find(detid); - if ((hCharge != mHistogramClchgDE.end()) && (hCharge->second != NULL)) { - hCharge->second->Fill(chargeTot); - } - auto hChargeOnCycle = mHistogramClchgDEOnCycle.find(detid); - if ((hChargeOnCycle != mHistogramClchgDEOnCycle.end()) && (hChargeOnCycle->second != NULL)) { - hChargeOnCycle->second->Fill(chargeTot); - } - - // filter out clusters with small charge, which are likely to be noise - // and should not be used for estimating the pseudo-efficiency - if ((chargeMax[0] < 100) && (chargeMax[1] < 100)) { - return true; - } - + // compute center-of-gravity of the charge distribution double Xcog, Ycog; bool isWide[2]; CoG(preClusterDigits, Xcog, Ycog, isWide); - // Filling histograms to be used for Pseudo-efficiency computation + // criteria to define a "good" charge cluster in one cathode: + // - two or more digits + // - at least one digit with amplitude > 50 ADC + bool isGood[2] = { (chargeMax[0] > 50) && (isWide[0]), (chargeMax[1] > 50) && (isWide[1]) }; + //bool isGood[2] = {isWide[0], isWide[1]}; - // All meaningful preclusters (the breakdown is done in the histograms below) - if ((cathode[0] && isWide[0]) || (cathode[1] && isWide[1]) || (cathode[0] && cathode[1])) { + // Filling histograms to be used for Pseudo-efficiency computation + if (isGood[1]) { + // good cluster on non-bending side, check if there is data from the bending side as well auto hXY0 = mHistogramPreclustersXY[0].find(detid); if ((hXY0 != mHistogramPreclustersXY[0].end()) && (hXY0->second != NULL)) { - hXY0->second->Fill(Xcog, Ycog); + hXY0->second->Fill(Xcog, Ycog, 0.5, 0.5); + } + if (cathode[0]) { //Check if associated to something on Bending + auto hXY1 = mHistogramPreclustersXY[2].find(detid); + if ((hXY1 != mHistogramPreclustersXY[2].end()) && (hXY1->second != NULL)) { + hXY1->second->Fill(Xcog, Ycog, 0.5, 0.5); + } } } - // Wide clusters on bending side (because mono-cathode preclusters need to be wide to have a meaningful position in both x and y) - if (cathode[0] && isWide[0]) { - auto hXY1 = mHistogramPreclustersXY[1].find(detid); - if ((hXY1 != mHistogramPreclustersXY[1].end()) && (hXY1->second != NULL)) { - hXY1->second->Fill(Xcog, Ycog); + if (isGood[0]) { + // good cluster on bending side, check if there is data from the non-bending side as well + auto hXY0 = mHistogramPreclustersXY[1].find(detid); + if ((hXY0 != mHistogramPreclustersXY[1].end()) && (hXY0->second != NULL)) { + hXY0->second->Fill(Xcog, Ycog, 0.5, 0.5); } - } - // Similarly on non-bending - if (cathode[1] && isWide[1]) { - auto hXY1 = mHistogramPreclustersXY[2].find(detid); - if ((hXY1 != mHistogramPreclustersXY[2].end()) && (hXY1->second != NULL)) { - hXY1->second->Fill(Xcog, Ycog); + if (cathode[1]) { //Check if associated to something on Non-Bending + auto hXY1 = mHistogramPreclustersXY[3].find(detid); + if ((hXY1 != mHistogramPreclustersXY[3].end()) && (hXY1->second != NULL)) { + hXY1->second->Fill(Xcog, Ycog, 0.5, 0.5); + } } } - // Clusters on both bending and non-bending (no need to require them to be wide because having both cathodes fired is sufficient to give x and y with enough precision) - if (cathode[0] && cathode[1]) { - auto hXY1 = mHistogramPreclustersXY[3].find(detid); - if ((hXY1 != mHistogramPreclustersXY[3].end()) && (hXY1->second != NULL)) { - hXY1->second->Fill(Xcog, Ycog); + + // This code is slow. Will be re-introduced after some optimizations + //const o2::mch::mapping::CathodeSegmentation& csegment = segment.bending(); + //o2::mch::contour::Contour envelop = o2::mch::mapping::getEnvelop(csegment); + //std::vector> vertices = envelop.getVertices(); + //o2::mch::contour::BBox bbox = o2::mch::mapping::getBBox(csegment); + //std::cout<<"DE "< (bbox.xmax() - 5)) return true; + //if(Ycog < (bbox.ymin() + 5)) return true; + //if(Ycog > (bbox.ymax() - 5)) return true; + + // cluster size, separately on each cathode and combined + auto hSize = mHistogramClsizeDE.find(detid); + if ((hSize != mHistogramClsizeDE.end()) && (hSize->second != NULL)) { + hSize->second->Fill(multiplicity[0], 0); + hSize->second->Fill(multiplicity[1], 1); + hSize->second->Fill(multiplicity[0] + multiplicity[1], 2); + } + + float chargeTot = chargeSum[0] + chargeSum[1]; + auto hCharge = mHistogramClchgDE.find(detid); + if ((hCharge != mHistogramClchgDE.end()) && (hCharge->second != NULL)) { + if ((multiplicity[0] <= 1) && (multiplicity[1] <= 1)) { + hCharge->second->Fill(chargeTot, 0); + } else if ((multiplicity[0] > 1) && (multiplicity[1] == 1)) { + hCharge->second->Fill(chargeTot, 1); + } else if ((multiplicity[0] <= 1) && (multiplicity[1] > 1)) { + hCharge->second->Fill(chargeTot, 2); + } else if ((multiplicity[0] > 1) && (multiplicity[1] > 1)) { + hCharge->second->Fill(chargeTot, 3); } } + auto hChargeOnCycle = mHistogramClchgDEOnCycle.find(detid); + if ((hChargeOnCycle != mHistogramClchgDEOnCycle.end()) && (hChargeOnCycle->second != NULL)) { + hChargeOnCycle->second->Fill(chargeTot); + } + return (cathode[0] && cathode[1]); } //_________________________________________________________________________________________________ -void PhysicsTaskPreclusters::printPreclusters(gsl::span preClusters, gsl::span digits) +void PhysicsTaskPreclusters::printPrecluster(gsl::span preClusterDigits) { - for (auto& preCluster : preClusters) { - // get the digits of this precluster - auto preClusterDigits = digits.subspan(preCluster.firstDigit, preCluster.nDigits); - - float chargeSum[2] = { 0, 0 }; - float chargeMax[2] = { 0, 0 }; + float chargeSum[2] = { 0, 0 }; + float chargeMax[2] = { 0, 0 }; - int detid = preClusterDigits[0].getDetID(); - const o2::mch::mapping::Segmentation& segment = o2::mch::mapping::segmentation(detid); + int detid = preClusterDigits[0].getDetID(); + const o2::mch::mapping::Segmentation& segment = o2::mch::mapping::segmentation(detid); - for (const o2::mch::Digit& digit : preClusterDigits) { - int padid = digit.getPadID(); + for (ssize_t i = 0; (unsigned)i < preClusterDigits.size(); ++i) { + const o2::mch::Digit& digit = preClusterDigits[i]; + int padid = digit.getPadID(); - // cathode index - int cid = segment.isBendingPad(padid) ? 0 : 1; - chargeSum[cid] += digit.getADC(); + // cathode index + int cid = segment.isBendingPad(padid) ? 0 : 1; + chargeSum[cid] += digit.getADC(); - if (digit.getADC() > chargeMax[cid]) { - chargeMax[cid] = digit.getADC(); - } + if (digit.getADC() > chargeMax[cid]) { + chargeMax[cid] = digit.getADC(); } + } - double Xcog, Ycog; - bool isWide[2]; - CoG(preClusterDigits, Xcog, Ycog, isWide); - - QcInfoLogger::GetInstance() << "[pre-cluster] charge = " << chargeSum[0] << " " << chargeSum[1] << " CoG = " << Xcog << " " << AliceO2::InfoLogger::InfoLogger::endm; - for (auto& d : preClusterDigits) { - float X = segment.padPositionX(d.getPadID()); - float Y = segment.padPositionY(d.getPadID()); - bool bend = !segment.isBendingPad(d.getPadID()); - QcInfoLogger::GetInstance() << fmt::format(" DE {:4d} PAD {:5d} ADC {:6d} TIME (XXX)", - d.getDetID(), d.getPadID(), d.getADC()) - << "\n" - << fmt::format(" CATHODE {} PAD_XY {:+2.2f} , {:+2.2f}", (int)bend, X, Y) << AliceO2::InfoLogger::InfoLogger::endm; - } + double Xcog, Ycog; + bool isWide[2]; + CoG(preClusterDigits, Xcog, Ycog, isWide); + + QcInfoLogger::GetInstance() << "\n\n\n====================\n" + << "[pre-cluster] nDigits = " << preClusterDigits.size() << " charge = " << chargeSum[0] << " " << chargeSum[1] << " CoG = " << Xcog << "," << Ycog << AliceO2::InfoLogger::InfoLogger::endm; + for (auto& d : preClusterDigits) { + float X = segment.padPositionX(d.getPadID()); + float Y = segment.padPositionY(d.getPadID()); + bool bend = !segment.isBendingPad(d.getPadID()); + QcInfoLogger::GetInstance() << fmt::format(" DE {:4d} PAD {:5d} ADC {:6d} TIME ({})", + d.getDetID(), d.getPadID(), d.getADC(), d.getTime()) + << "\n" + << fmt::format(" CATHODE {} PAD_XY {:+2.2f} , {:+2.2f}", (int)bend, X, Y) << AliceO2::InfoLogger::InfoLogger::endm; } + QcInfoLogger::GetInstance() << "\n====================\n\n" + << AliceO2::InfoLogger::InfoLogger::endm; } -void PhysicsTaskPreclusters::endOfCycle() +//_________________________________________________________________________________________________ +void PhysicsTaskPreclusters::printPreclusters(gsl::span preClusters, gsl::span digits) { - QcInfoLogger::GetInstance() << "endOfCycle" << AliceO2::InfoLogger::InfoLogger::endm; - for (int de = 100; de <= 1030; de++) { - for (int i = 0; i < 3; i++) { - auto ih = mHistogramPreclustersXY[i + 1].find(de); - if (ih == mHistogramPreclustersXY[i + 1].end()) { + for (auto& preCluster : preClusters) { + // get the digits of this precluster + auto preClusterDigits = digits.subspan(preCluster.firstDigit, preCluster.nDigits); + printPrecluster(preClusterDigits); + } +} + +void PhysicsTaskPreclusters::computePseudoEfficiency() +{ + for (auto de : o2::mch::raw::deIdsForAllMCH) { + for (int i = 0; i < 2; i++) { + auto ih = mHistogramPreclustersXY[i + 2].find(de); + if (ih == mHistogramPreclustersXY[i + 2].end()) { continue; } // Getting the histogram with the clusters positions exists (either on B, NB, or B and NB) @@ -383,8 +434,8 @@ void PhysicsTaskPreclusters::endOfCycle() } // Getting the histogram with all the preclusters (denominator of pseudo-efficiency) - ih = mHistogramPreclustersXY[0].find(de); - if (ih == mHistogramPreclustersXY[0].end()) { + ih = mHistogramPreclustersXY[i].find(de); + if (ih == mHistogramPreclustersXY[i].end()) { continue; } TH2F* hAll = ih->second; @@ -393,66 +444,40 @@ void PhysicsTaskPreclusters::endOfCycle() } // Checking the Histograms where Pseudo-efficiency should be stored and resetting them - ih = mHistogramPseudoeffXY[i].find(de); - if (ih == mHistogramPseudoeffXY[i].end()) { + auto ihp = mHistogramPseudoeffXY[i].find(de); + if (ihp == mHistogramPseudoeffXY[i].end()) { continue; } - TH2F* hEff = ih->second; + MergeableTH2Ratio* hEff = ihp->second; if (!hEff) { continue; } - // Computing the Pseudo-efficiency by dividing the distrobution of clusters (either on B, NB, or B and NB) by the total distribution of all clusters. - hEff->Reset(); - hEff->Add(hB); - hEff->Divide(hAll); + // Computing the Pseudo-efficiency by dividing the distribution of clusters (either on B, NB, or B and NB) by the total distribution of all clusters. + ihp->second->update(); } } // Same procedure but in GlobalHistograms - mHistogramPseudoeff[0]->add(mHistogramPreclustersXY[0], mHistogramPreclustersXY[0]); - mHistogramPseudoeff[1]->add(mHistogramPreclustersXY[1], mHistogramPreclustersXY[2]); - mHistogramPseudoeff[1]->Divide(mHistogramPseudoeff[0]); - mHistogramPseudoeff[2]->add(mHistogramPreclustersXY[3], mHistogramPreclustersXY[3]); - mHistogramPseudoeff[2]->Divide(mHistogramPseudoeff[0]); - - // Using PseudoeffXY to get the mean pseudoeff per DE on last cycle - // By counting how many preclusters have been seen in total compared to how many have been seen on B and NB, on each DE - auto hMean = mMeanPseudoeffPerDE; - auto hMeanCycle = mMeanPseudoeffPerDECycle; - - for (int de = 0; de < 1100; de++) { - auto hnum = mHistogramPreclustersXY[0].find(de); - auto hBNB = mHistogramPreclustersXY[3].find(de); - if ((hBNB != mHistogramPreclustersXY[3].end()) && (hBNB->second != NULL) && (hnum != mHistogramPreclustersXY[0].end()) && (hnum->second != NULL)) { - NewPreclBNBDE[de] = 0; - NewPreclNumDE[de] = 0; - for (int binx = 1; binx < hBNB->second->GetXaxis()->GetNbins() + 1; binx++) { - for (int biny = 1; biny < hBNB->second->GetYaxis()->GetNbins() + 1; biny++) { - NewPreclBNBDE[de] += hBNB->second->GetBinContent(binx, biny); - } - } - for (int binx = 1; binx < hnum->second->GetXaxis()->GetNbins() + 1; binx++) { - for (int biny = 1; biny < hnum->second->GetYaxis()->GetNbins() + 1; biny++) { - NewPreclNumDE[de] += hnum->second->GetBinContent(binx, biny); - } - } - } - } - for (int i = 0; i < 1100; i++) { - MeanPseudoeffDE[i] = 0; - MeanPseudoeffDECycle[i] = 0; - if (NewPreclNumDE[i] > 0) { - MeanPseudoeffDE[i] = NewPreclBNBDE[i] / NewPreclNumDE[i]; - } - if ((NewPreclNumDE[i] - LastPreclNumDE[i]) > 0) { - MeanPseudoeffDECycle[i] = (NewPreclBNBDE[i] - LastPreclBNBDE[i]) / (NewPreclNumDE[i] - LastPreclNumDE[i]); - } - hMean->SetBinContent(i + 1, MeanPseudoeffDE[i]); - hMeanCycle->SetBinContent(i + 1, MeanPseudoeffDECycle[i]); - LastPreclBNBDE[i] = NewPreclBNBDE[i]; - LastPreclNumDE[i] = NewPreclNumDE[i]; - } + mHistogramPseudoeff_NumsAndDens[0]->add(mHistogramPreclustersXY[0], mHistogramPreclustersXY[1]); + mHistogramPseudoeff_NumsAndDens[1]->add(mHistogramPreclustersXY[2], mHistogramPreclustersXY[3]); + + mHistogramPseudoeff->update(); + + mMeanPseudoeffPerDE_DoesGoodNBHaveSomethingB->update(); + mMeanPseudoeffPerDE_DoesGoodBHaveSomethingNB->update(); + + mMeanPseudoeffPerDE_DoesGoodNBHaveSomethingB_Cycle->update(); + mMeanPseudoeffPerDE_DoesGoodBHaveSomethingNB_Cycle->update(); + + mMPVCycle->update(); +} + +void PhysicsTaskPreclusters::endOfCycle() +{ + QcInfoLogger::GetInstance() << "endOfCycle" << AliceO2::InfoLogger::InfoLogger::endm; + + computePseudoEfficiency(); } void PhysicsTaskPreclusters::endOfActivity(Activity& /*activity*/) @@ -460,13 +485,19 @@ void PhysicsTaskPreclusters::endOfActivity(Activity& /*activity*/) QcInfoLogger::GetInstance() << "endOfActivity" << AliceO2::InfoLogger::InfoLogger::endm; #ifdef QC_MCH_SAVE_TEMP_ROOTFILE - TFile f("/tmp/qc.root", "RECREATE"); + computePseudoEfficiency(); + + TFile f("mch-qc-preclusters.root", "RECREATE"); { - auto hMean = mMeanPseudoeffPerDE; - auto hMeanCycle = mMeanPseudoeffPerDECycle; + auto hMean = mMeanPseudoeffPerDE_DoesGoodNBHaveSomethingB; + auto hMean2 = mMeanPseudoeffPerDE_DoesGoodBHaveSomethingNB; + auto hMeanCycle = mMeanPseudoeffPerDE_DoesGoodNBHaveSomethingB_Cycle; + auto hMeanCycle2 = mMeanPseudoeffPerDE_DoesGoodBHaveSomethingNB_Cycle; hMean->Write(); + hMean2->Write(); hMeanCycle->Write(); + hMeanCycle2->Write(); } { @@ -477,6 +508,13 @@ void PhysicsTaskPreclusters::endOfActivity(Activity& /*activity*/) } } } + for (int i = 0; i < 2; i++) { + for (auto& h2 : mHistogramPseudoeffXY[i]) { + if (h2.second != nullptr) { + h2.second->Write(); + } + } + } for (auto& h : mHistogramClchgDE) { if (h.second != nullptr) { h.second->Write(); @@ -488,11 +526,20 @@ void PhysicsTaskPreclusters::endOfActivity(Activity& /*activity*/) h.second->Reset(); } } + for (auto& h : mHistogramClsizeDE) { + if (h.second != nullptr) { + h.second->Write(); + h.second->Reset(); + } + } } - mHistogramPseudoeff[0]->Write(); - mHistogramPseudoeff[1]->Write(); - mHistogramPseudoeff[2]->Write(); + mHistogramPseudoeff_NumsAndDens[0]->Write(); + mHistogramPseudoeff_NumsAndDens[1]->Write(); + + mHistogramPseudoeff->Write(); + + mMPVCycle->Write(); f.Close();