diff --git a/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx b/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx index 38c9592169f..477e6875938 100644 --- a/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx +++ b/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx @@ -321,11 +321,10 @@ void o2::aod::emphotonhistograms::DefineHistograms(THashList* list, const char* } if (TString(histClass) == "Cluster") { - list->Add(new TH1F("hPt", "pT;p_{T} (GeV/c)", 1000, 0.0f, 10)); - list->Add(new TH2F("hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", 180, 0, 2 * M_PI, 400, -2.0f, 2.0f)); - list->Add(new TH1F("hNgamma", "Number of #gamma candidates per collision", 101, -0.5f, 100.5f)); - if (TString(subGroup) == "PHOS") { + list->Add(new TH1F("hPt", "pT;p_{T} (GeV/c)", 1000, 0.0f, 10)); + list->Add(new TH2F("hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", 180, 0, 2 * M_PI, 400, -2.0f, 2.0f)); + list->Add(new TH1F("hNgamma", "Number of #gamma candidates per collision", 101, -0.5f, 100.5f)); list->Add(new TH2F("hEvsNcell", "E_{cluster} vs. N_{cell};E_{cluster} (GeV);N_{cell}", 200, 0, 20, 51, -0.5, 50.5f)); list->Add(new TH2F("hEvsM02", "E_{cluster} vs. M02;E_{cluster} (GeV);M02 (cm)", 200, 0, 20, 100, 0, 10)); list->Add(new TH2F("hEvsM20", "E_{cluster} vs. M20;E_{cluster} (GeV);M20 (cm)", 200, 0, 20, 100, 0, 10)); @@ -336,6 +335,37 @@ void o2::aod::emphotonhistograms::DefineHistograms(THashList* list, const char* list->Add(new TH2F(Form("hClusterXZM%d", i), Form("cluster (X,Z) on M%d;X;Z", i), 64, 0.5, 64.5, 56, 0.5, 56.5)); } // end of module loop } + if (TString(subGroup).Contains("EMC")) { + list->Add(new TH1F("hPt", "Transverse momenta of clusters;#it{p}_{T} (GeV/c);#it{N}_{cluster}", 1000, 0.0f, 20)); + list->Add(new TH1F("hE", "E_{cluster};#it{E}_{cluster} (GeV);#it{N}_{cluster}", 500, 0, 50)); + list->Add(new TH1F("hNgamma", "Number of #gamma candidates per collision;#it{N}_{#gamma} per collision;#it{N}_{collisions}", 101, -0.5f, 100.5f)); + list->Add(new TH2F("hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", 180, 0, 2 * M_PI, 200, -1.0f, 1.0f)); + list->Add(new TH2F("hTrackEtaPhi", "d#eta vs. d#varphi of matched tracks;d#varphi (rad.);d#eta", 100, -0.5, 0.5, 100, -0.5, 0.5)); + if (TString(subGroup).Contains("2D")) { // Check if 2D QA histograms were selected in em-qc task + list->Add(new TH2F("hNCell", "#it{N}_{cells};N_{cells} (GeV);#it{E}_{cluster} (GeV)", 51, -0.5, 50.5, 200, 0, 20)); + list->Add(new TH2F("hM02", "Long ellipse axis;#it{M}_{02} (cm);#it{E}_{cluster} (GeV)", 500, 0, 5, 200, 0, 20)); + list->Add(new TH2F("hM20", "Short ellipse axis;#it{M}_{20} (cm);#it{E}_{cluster} (GeV)", 250, 0, 2.5, 200, 0, 20)); + list->Add(new TH2F("hTime", "Cluster time;#it{t}_{cls} (ns);#it{E}_{cluster} (GeV)", 100, -250, 250, 200, 0, 20)); + list->Add(new TH2F("hCellTime", "Cell time;#it{t}_{cell} (ns);#it{E}_{cluster} (GeV)", 100, -250, 250, 200, 0, 20)); + list->Add(new TH2F("hDistToBC", "distance to bad channel;#it{d};#it{E}_{cluster} (GeV)", 100, 0, 1500, 200, 0, 20)); + } else { + list->Add(new TH1F("hNCell", "#it{N}_{cells};N_{cells} (GeV);#it{N}_{cluster}", 51, -0.5, 50.5)); + list->Add(new TH1F("hM02", "Long ellipse axis;#it{M}_{02} (cm);#it{N}_{cluster}", 500, 0, 5)); + list->Add(new TH1F("hM20", "Short ellipse axis;#it{M}_{20} (cm);#it{N}_{cluster}", 250, 0, 2.5)); + list->Add(new TH1F("hTime", "Cluster time;#it{t}_{cls} (ns);#it{N}_{cluster}", 500, -250, 250)); + list->Add(new TH1F("hCellTime", "Cluster time;#it{t}_{cell} (ns);#it{N}_{cluster}", 500, -250, 250)); + list->Add(new TH1F("hDistToBC", "distance to bad channel;#it{d};#it{N}_{cluster}", 100, 0, 1500)); + } + list->Add(new TH2F("hClusterQualityCuts", "Energy at which clusters are removed by a given cut;;#it{E} (GeV)", 8, -0.5, 7.5, 500, 0, 50)); + reinterpret_cast(list->FindObject("hClusterQualityCuts"))->GetXaxis()->SetBinLabel(1, "In"); + reinterpret_cast(list->FindObject("hClusterQualityCuts"))->GetXaxis()->SetBinLabel(2, "Energy"); + reinterpret_cast(list->FindObject("hClusterQualityCuts"))->GetXaxis()->SetBinLabel(3, "NCell"); + reinterpret_cast(list->FindObject("hClusterQualityCuts"))->GetXaxis()->SetBinLabel(4, "M02"); + reinterpret_cast(list->FindObject("hClusterQualityCuts"))->GetXaxis()->SetBinLabel(5, "Timing"); + reinterpret_cast(list->FindObject("hClusterQualityCuts"))->GetXaxis()->SetBinLabel(6, "Track matching"); + reinterpret_cast(list->FindObject("hClusterQualityCuts"))->GetXaxis()->SetBinLabel(7, "Exotic"); + reinterpret_cast(list->FindObject("hClusterQualityCuts"))->GetXaxis()->SetBinLabel(8, "Out"); + } } if (TString(histClass) == "singlephoton") { diff --git a/PWGEM/PhotonMeson/Core/HistogramsLibrary.h b/PWGEM/PhotonMeson/Core/HistogramsLibrary.h index 7621e103409..7f477e981ff 100644 --- a/PWGEM/PhotonMeson/Core/HistogramsLibrary.h +++ b/PWGEM/PhotonMeson/Core/HistogramsLibrary.h @@ -142,6 +142,26 @@ void FillHistClass(THashList* list, const char* subGroup, T const& obj) reinterpret_cast(list->FindObject("hEvsM20"))->Fill(obj.e(), obj.m20()); reinterpret_cast(list->FindObject("hDistToBC"))->Fill(obj.distanceToBadChannel()); reinterpret_cast(list->FindObject(Form("hClusterXZM%d", obj.mod())))->Fill(obj.cellx(), obj.cellz()); + } else if constexpr (htype == EMHistType::kEMCCluster) { + if (TString(subGroup) == "2D") { + reinterpret_cast(list->FindObject("hNCell"))->Fill(obj.nCells(), obj.e()); + reinterpret_cast(list->FindObject("hM02"))->Fill(obj.m02(), obj.e()); + reinterpret_cast(list->FindObject("hM20"))->Fill(obj.m20(), obj.e()); + reinterpret_cast(list->FindObject("hTime"))->Fill(obj.time(), obj.e()); + reinterpret_cast(list->FindObject("hDistToBC"))->Fill(obj.distanceToBadChannel(), obj.e()); + } else { + reinterpret_cast(list->FindObject("hNCell"))->Fill(obj.nCells()); + reinterpret_cast(list->FindObject("hM02"))->Fill(obj.m02()); + reinterpret_cast(list->FindObject("hM20"))->Fill(obj.m20()); + reinterpret_cast(list->FindObject("hTime"))->Fill(obj.time()); + reinterpret_cast(list->FindObject("hDistToBC"))->Fill(obj.distanceToBadChannel()); + } + reinterpret_cast(list->FindObject("hPt"))->Fill(obj.pt()); + reinterpret_cast(list->FindObject("hE"))->Fill(obj.e()); + reinterpret_cast(list->FindObject("hEtaPhi"))->Fill(obj.phi(), obj.eta()); + for (int itrack = 0; itrack < obj.tracketa().size(); itrack++) { // Fill TrackEtaPhi histogram with delta phi and delta eta of all tracks saved in the vectors in skimmerGammaCalo.cxx + reinterpret_cast(list->FindObject("hTrackEtaPhi"))->Fill(obj.trackphi()[itrack] - obj.phi(), obj.tracketa()[itrack] - obj.eta()); + } } } } // namespace emphotonhistograms diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx index a696474d52a..b2b13b8aac2 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx @@ -79,7 +79,7 @@ struct skimmerGammaCalo { continue; } // M02 cut - if (emccluster.m02() > maxM02 || emccluster.m02() < minM02) { + if (emccluster.nCells() > 1 && (emccluster.m02() > maxM02 || emccluster.m02() < minM02)) { historeg.fill(HIST("hCaloClusterFilter"), 2); continue; } diff --git a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt index ed0269970b4..c3bf7fe18e5 100644 --- a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt @@ -54,6 +54,11 @@ o2physics_add_dpl_workflow(dalitz-mumu-qc-mc PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(emcal-qc + SOURCES emcalQC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phos-qc SOURCES phosQC.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGamma.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGamma.cxx index 969e6f49bee..7839c019f0b 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGamma.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGamma.cxx @@ -372,7 +372,7 @@ struct Pi0EtaToGammaGamma { if ((pairtype == PairType::kPHOSPHOS || pairtype == PairType::kPCMPHOS) && !collision.isPHOSCPVreadout()) { continue; } - if ((pairtype == PairType::kEMCEMC || pairtype == PairType::kPCMEMC) && !collision.isEMCreadout()) { + if ((pairtype == PairType::kEMCEMC || pairtype == PairType::kPCMEMC) && (!collision.isEMCreadout() || collision.ncollsPerBC() != 1)) { continue; } diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMC.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMC.cxx index 245fea0e4c0..a44c838fe29 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMC.cxx @@ -550,7 +550,7 @@ struct Pi0EtaToGammaGammaMC { if ((pairtype == kPHOSPHOS || pairtype == kPCMPHOS) && !collision.isPHOSCPVreadout()) { continue; // I don't know why this is necessary in simulation. } - if ((pairtype == kEMCEMC || pairtype == kPCMEMC) && !collision.isEMCreadout()) { + if ((pairtype == kEMCEMC || pairtype == kPCMEMC) && (!collision.isEMCreadout() || collision.ncollsPerBC() != 1)) { continue; // I don't know why this is necessary in simulation. } diff --git a/PWGEM/PhotonMeson/Tasks/emcalQC.cxx b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx new file mode 100644 index 00000000000..2daf9eafe4d --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx @@ -0,0 +1,232 @@ +// Copyright 2019-2024 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// 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. +// +// ======================== +// +// This code runs loop over EMCal clusters for EMCal QC. +// Please write to: nicolas.strangmann@cern.ch + +#include +#include "TString.h" +#include "THashList.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/trackUtilities.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/Core/RecoDecay.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" +#include "PWGEM/PhotonMeson/Core/CutsLibrary.h" +#include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using std::array; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +struct emcalQC { + + Configurable fConfigEMCCuts{"cfgEMCCuts", "custom,standard,nocut", "Comma separated list of EMCal photon cuts"}; + Configurable EMC_minTime{"EMC_minTime", -20., "Minimum cluster time for EMCal time cut"}; + Configurable EMC_maxTime{"EMC_maxTime", +25., "Maximum cluster time for EMCal time cut"}; + Configurable EMC_minM02{"EMC_minM02", 0.1, "Minimum M02 for EMCal M02 cut"}; + Configurable EMC_maxM02{"EMC_maxM02", 0.7, "Maximum M02 for EMCal M02 cut"}; + Configurable EMC_minE{"EMC_minE", 0.7, "Minimum cluster energy for EMCal energy cut"}; + Configurable EMC_minNCell{"EMC_minNCell", 1, "Minimum number of cells per cluster for EMCal NCell cut"}; + Configurable> EMC_TM_Eta{"EMC_TM_Eta", {0.01f, 4.07f, -2.5f}, "|eta| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + Configurable> EMC_TM_Phi{"EMC_TM_Phi", {0.015f, 3.65f, -2.f}, "|phi| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + Configurable EMC_Eoverp{"EMC_Eoverp", 1.75, "Minimum cluster energy over track momentum for EMCal track matching"}; + Configurable EMC_UseExoticCut{"EMC_UseExoticCut", true, "FLag to use the EMCal exotic cluster cut"}; + Configurable fDo2DQC{"Do2DQC", true, "Flag to output 2D QC histograms displaying the energy dependence on the second axis"}; + + std::vector fEMCCuts; + + OutputObj fOutputEvent{"Event"}; + OutputObj fOutputCluster{"Cluster"}; + THashList* fMainList = new THashList(); + + void addhistograms() + { + fMainList->SetOwner(true); + fMainList->SetName("fMainList"); + + // create sub lists first. + o2::aod::emphotonhistograms::AddHistClass(fMainList, "Event"); + THashList* list_ev = reinterpret_cast(fMainList->FindObject("Event")); + o2::aod::emphotonhistograms::DefineHistograms(list_ev, "Event"); + + o2::aod::emphotonhistograms::AddHistClass(fMainList, "Cluster"); + THashList* list_cluster = reinterpret_cast(fMainList->FindObject("Cluster")); + + for (const auto& cut : fEMCCuts) { + const char* cutname = cut.GetName(); + o2::aod::emphotonhistograms::AddHistClass(list_cluster, cutname); + } + + // for Clusters + for (auto& cut : fEMCCuts) { + std::string_view cutname = cut.GetName(); + THashList* list = reinterpret_cast(fMainList->FindObject("Cluster")->FindObject(cutname.data())); + o2::aod::emphotonhistograms::DefineHistograms(list, "Cluster", fDo2DQC ? "2D_EMC" : "EMC"); + } + } + + void DefineCuts() + { + const float a = EMC_TM_Eta->at(0); + const float b = EMC_TM_Eta->at(1); + const float c = EMC_TM_Eta->at(2); + + const float d = EMC_TM_Phi->at(0); + const float e = EMC_TM_Phi->at(1); + const float f = EMC_TM_Phi->at(2); + LOGF(info, "EMCal track matching parameters : a = %f, b = %f, c = %f, d = %f, e = %f, f = %f", a, b, c, d, e, f); + + TString cutNamesStr = fConfigEMCCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + if (std::strcmp(cutname, "custom") == 0) { + EMCPhotonCut* custom_cut = new EMCPhotonCut(cutname, cutname); + custom_cut->SetMinE(EMC_minE); + custom_cut->SetMinNCell(EMC_minNCell); + custom_cut->SetM02Range(EMC_minM02, EMC_maxM02); + custom_cut->SetTimeRange(EMC_minTime, EMC_maxTime); + + custom_cut->SetTrackMatchingEta([&a, &b, &c](float pT) { + return a + pow(pT + b, c); + }); + custom_cut->SetTrackMatchingPhi([&d, &e, &f](float pT) { + return d + pow(pT + e, f); + }); + + custom_cut->SetMinEoverP(EMC_Eoverp); + custom_cut->SetUseExoticCut(EMC_UseExoticCut); + fEMCCuts.push_back(*custom_cut); + } else { + fEMCCuts.push_back(*aod::emccuts::GetCut(cutname)); + } + } + } + LOGF(info, "Number of EMC cuts = %d", fEMCCuts.size()); + } + + void init(InitContext& context) + { + DefineCuts(); + addhistograms(); // please call this after DefinCuts(); + + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(1, "all cols"); + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(2, "sel8 + readout"); + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(3, "1+ Contributor"); + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(4, "z<10cm"); + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->GetXaxis()->SetBinLabel(5, "unique col"); + + fOutputEvent.setObject(reinterpret_cast(fMainList->FindObject("Event"))); + fOutputCluster.setObject(reinterpret_cast(fMainList->FindObject("Cluster"))); + } + + Preslice perCollision = aod::skimmedcluster::collisionId; + + void processQC(MyCollisions const& collisions, aod::SkimEMCClusters const& clusters) + { + THashList* list_ev = static_cast(fMainList->FindObject("Event")); + THashList* list_cluster = static_cast(fMainList->FindObject("Cluster")); + + for (auto& collision : collisions) { + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hZvtx_before"))->Fill(collision.posZ()); + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->Fill(1.0); + if (!collision.sel8() || collision.isEMCreadout() == 0) { // Check sel8 and whether EMC was read out + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->Fill(2.0); + + if (collision.numContrib() < 0.5) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->Fill(3.0); + + if (abs(collision.posZ()) > 10.0) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->Fill(4.0); + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hZvtx_after"))->Fill(collision.posZ()); + + if (collision.ncollsPerBC() != 1) { // Check that the collision is unique (the only one in the bc) + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->Fill(5.0); + + o2::aod::emphotonhistograms::FillHistClass(list_ev, "", collision); // Fill event histograms + + auto clusters_per_coll = clusters.sliceBy(perCollision, collision.collisionId()); + for (const auto& cut : fEMCCuts) { + THashList* list_cluster_cut = static_cast(list_cluster->FindObject(cut.GetName())); + int ng = 0; + for (auto& cluster : clusters_per_coll) { + // Fill the cluster properties before applying any cuts + + // Apply cuts one by one and fill in hClusterQualityCuts histogram + reinterpret_cast(fMainList->FindObject("Cluster")->FindObject(cut.GetName())->FindObject("hClusterQualityCuts"))->Fill(0., cluster.e()); + auto track = nullptr; + + // Define two boleans to see, whether the cluster "survives" the EMC cluster cuts to later check, whether the cuts in this task align with the ones in EMCPhotonCut.h: + bool survivesIsSelectedEMCalCuts = true; // Survives "manual" cuts listed in this task + bool survivesIsSelectedCuts = cut.IsSelected(cluster); // Survives the cutlist defines in EMCPhotonCut.h, which is also used in the Pi0Eta task + + for (int icut = 0; icut < static_cast(EMCPhotonCut::EMCPhotonCuts::kNCuts); icut++) { // Loop through different cut observables + EMCPhotonCut::EMCPhotonCuts specificcut = static_cast(icut); + if (!cut.IsSelectedEMCal(specificcut, cluster, track)) { // Check whether cluster passes this cluster requirement, if not, fill why in the next row + reinterpret_cast(fMainList->FindObject("Cluster")->FindObject(cut.GetName())->FindObject("hClusterQualityCuts"))->Fill(icut + 1, cluster.e()); + survivesIsSelectedEMCalCuts = false; + } + } + + if (survivesIsSelectedCuts != survivesIsSelectedEMCalCuts) { + LOGF(info, "Cummulative application of IsSelectedEMCal cuts does not equal the IsSelected result"); + } + + if (survivesIsSelectedCuts) { + o2::aod::emphotonhistograms::FillHistClass(list_cluster_cut, fDo2DQC ? "2D" : "1D", cluster); + reinterpret_cast(fMainList->FindObject("Cluster")->FindObject(cut.GetName())->FindObject("hClusterQualityCuts"))->Fill(7., cluster.e()); + ng++; + } + } + reinterpret_cast(fMainList->FindObject("Cluster")->FindObject(cut.GetName())->FindObject("hNgamma"))->Fill(ng); + } // end of cut loop + } // end of collision loop + } // end of process + + void processDummy(MyCollisions const& collisions) {} + + PROCESS_SWITCH(emcalQC, processQC, "run EMCal QC", false); + PROCESS_SWITCH(emcalQC, processDummy, "Dummy function", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"emcal-qc"})}; +}