|
| 1 | +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. |
| 2 | +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. |
| 3 | +// All rights not expressly granted are reserved. |
| 4 | +// |
| 5 | +// This software is distributed under the terms of the GNU General Public |
| 6 | +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". |
| 7 | +// |
| 8 | +// In applying this license CERN does not waive the privileges and immunities |
| 9 | +// granted to it by virtue of its status as an Intergovernmental Organization |
| 10 | +// or submit itself to any jurisdiction. |
| 11 | + |
| 12 | +/// \file testPV.cxx |
| 13 | +/// \brief a task to check PV quality in MC |
| 14 | +/// \author daiki.sekihata@cern.ch |
| 15 | + |
| 16 | +#include "Common/CCDB/EventSelectionParams.h" |
| 17 | +#include "Common/DataModel/EventSelection.h" |
| 18 | + |
| 19 | +#include <Framework/AnalysisDataModel.h> |
| 20 | +#include <Framework/AnalysisHelpers.h> |
| 21 | +#include <Framework/AnalysisTask.h> |
| 22 | +#include <Framework/Configurable.h> |
| 23 | +#include <Framework/HistogramRegistry.h> |
| 24 | +#include <Framework/HistogramSpec.h> |
| 25 | +#include <Framework/InitContext.h> |
| 26 | +#include <Framework/runDataProcessing.h> |
| 27 | + |
| 28 | +#include <string> |
| 29 | + |
| 30 | +using namespace o2; |
| 31 | +using namespace o2::soa; |
| 32 | +using namespace o2::framework; |
| 33 | +using namespace o2::framework::expressions; |
| 34 | +using namespace o2::constants::physics; |
| 35 | + |
| 36 | +struct testPV { |
| 37 | + |
| 38 | + // Configurables |
| 39 | + // Configurable<std::string> ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; |
| 40 | + |
| 41 | + struct : ConfigurableGroup { |
| 42 | + std::string prefix = "eventCut"; |
| 43 | + Configurable<int> cfgEventGeneratorId{"cfgEventGeneratorId", -1, "event generator index. e.g. select gap/signal events"}; |
| 44 | + Configurable<float> cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; |
| 45 | + Configurable<float> cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; |
| 46 | + Configurable<bool> cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND"}; |
| 47 | + Configurable<bool> cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border"}; |
| 48 | + Configurable<bool> cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border"}; |
| 49 | + Configurable<bool> cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; |
| 50 | + Configurable<bool> cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; |
| 51 | + Configurable<bool> cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. |
| 52 | + Configurable<bool> cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. |
| 53 | + // for RCT |
| 54 | + o2::framework::Configurable<bool> cfgRequireGoodRCT{"cfgRequireGoodRCT", true, "require good detector flag in run condtion table"}; |
| 55 | + o2::framework::Configurable<std::string> cfgRCTLabel{"cfgRCTLabel", "CBT", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; |
| 56 | + o2::framework::Configurable<bool> cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for AA"}; |
| 57 | + o2::framework::Configurable<bool> cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; |
| 58 | + } eventCut; |
| 59 | + |
| 60 | + HistogramRegistry fRegistry{"fRegistry"}; |
| 61 | + |
| 62 | + void init(o2::framework::InitContext&) |
| 63 | + { |
| 64 | + // ccdb->setURL(ccdburl); |
| 65 | + // ccdb->setCaching(true); |
| 66 | + // ccdb->setLocalObjectValidityChecking(); |
| 67 | + // ccdb->setFatalWhenNull(false); |
| 68 | + |
| 69 | + mRunNumber = 0; |
| 70 | + |
| 71 | + addHistograms(); |
| 72 | + } |
| 73 | + |
| 74 | + int mRunNumber{0}; |
| 75 | + // Service<o2::ccdb::BasicCCDBManager> ccdb; |
| 76 | + |
| 77 | + template <typename TBC> |
| 78 | + void initCCDB(TBC const& bc) |
| 79 | + { |
| 80 | + if (mRunNumber == bc.runNumber()) { |
| 81 | + return; |
| 82 | + } |
| 83 | + |
| 84 | + mRunNumber = bc.runNumber(); |
| 85 | + } |
| 86 | + |
| 87 | + void addHistograms() |
| 88 | + { |
| 89 | + auto hCollisionCounter = fRegistry.add<TH1>("hCollisionCounter", "collision counter", kTH1D, {{2, 0.5f, 2.5f}}, false); |
| 90 | + hCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); |
| 91 | + hCollisionCounter->GetXaxis()->SetBinLabel(2, "accepted"); |
| 92 | + |
| 93 | + fRegistry.add("Vertex/hZvtx", "vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); |
| 94 | + fRegistry.add("Vertex/hNContrib", "Number of PV contributors;N_{contrib}", kTH1F, {{101, -0.5, 100.5}}, false); |
| 95 | + fRegistry.add("Vertex/hChi2", "vertex chi2;#chi^{2}/N_{contrib}", kTH1F, {{100, 0, 10}}, false); |
| 96 | + fRegistry.add("Vertex/hChi2vsNContrib", "vertex #chi^{2}/N_{contrib} vs. N_{contrib};N_{contrib};#chi^{2}/N_{contrib}", kTH2F, {{101, -0.5, 100.5}, {100, 0, 10}}, false); |
| 97 | + |
| 98 | + fRegistry.add("Vertex/hSigmaX", "vertex #sigma_{X} vs. N_{contrib};N_{contrib};#sigma_{X} (#mum)", kTH2F, {{101, -0.5, 100.5}, {1000, 0, 100}}, false); |
| 99 | + fRegistry.add("Vertex/hSigmaY", "vertex #sigma_{Y} vs. N_{contrib};N_{contrib};#sigma_{Y} (#mum)", kTH2F, {{101, -0.5, 100.5}, {1000, 0, 100}}, false); |
| 100 | + fRegistry.add("Vertex/hSigmaZ", "vertex #sigma_{Z} vs. N_{contrib};N_{contrib};#sigma_{Z} (#mum)", kTH2F, {{101, -0.5, 100.5}, {1000, 0, 100}}, false); |
| 101 | + |
| 102 | + fRegistry.add("Vertex/hDeltaX", "vertex #DeltaX vs. N_{contrib};N_{contrib};#DeltaX = (X_{rec} #minus X_{gen})/#sigma_{X}", kTH2F, {{101, -0.5, 100.5}, {200, -10, 10}}, false); |
| 103 | + fRegistry.add("Vertex/hDeltaY", "vertex #DeltaY vs. N_{contrib};N_{contrib};#DeltaY = (Y_{rec} #minus Y_{gen})/#sigma_{Y}", kTH2F, {{101, -0.5, 100.5}, {200, -10, 10}}, false); |
| 104 | + fRegistry.add("Vertex/hDeltaZ", "vertex #DeltaZ vs. N_{contrib};N_{contrib};#DeltaZ = (Z_{rec} #minus Z_{gen})/#sigma_{Z}", kTH2F, {{101, -0.5, 100.5}, {200, -10, 10}}, false); |
| 105 | + |
| 106 | + fRegistry.add("Vertex/hCollisionTime", "vertex time;N_{contrib};collision time (ns)", kTH2F, {{101, -0.5, 100.5}, {500, -25, 25}}, false); |
| 107 | + fRegistry.add("Vertex/hCollisionTimeRes", "vertex time resolution;N_{contrib};collision time resolution (ns)", kTH2F, {{101, -0.5, 100.5}, {250, 0, 25}}, false); |
| 108 | + } |
| 109 | + |
| 110 | + template <typename TCollision> |
| 111 | + bool isSelectedCollision(TCollision const& collision) |
| 112 | + { |
| 113 | + if (!(eventCut.cfgZvtxMin < collision.posZ() && collision.posZ() < eventCut.cfgZvtxMax)) { |
| 114 | + return false; |
| 115 | + } |
| 116 | + if (eventCut.cfgRequireFT0AND && !collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { |
| 117 | + return false; |
| 118 | + } |
| 119 | + if (eventCut.cfgRequireNoTFB && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { |
| 120 | + return false; |
| 121 | + } |
| 122 | + if (eventCut.cfgRequireNoITSROFB && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { |
| 123 | + return false; |
| 124 | + } |
| 125 | + if (eventCut.cfgRequireNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { |
| 126 | + return false; |
| 127 | + } |
| 128 | + if (eventCut.cfgRequireGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { |
| 129 | + return false; |
| 130 | + } |
| 131 | + if (eventCut.cfgRequireVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { |
| 132 | + return false; |
| 133 | + } |
| 134 | + if (eventCut.cfgRequireVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { |
| 135 | + return false; |
| 136 | + } |
| 137 | + return true; |
| 138 | + } |
| 139 | + |
| 140 | + template <typename TCollision, typename TMCCollision> |
| 141 | + void fillVertexHistograms(TCollision const& collision, TMCCollision const& mcCollision) |
| 142 | + { |
| 143 | + fRegistry.fill(HIST("Vertex/hZvtx"), collision.posZ()); |
| 144 | + fRegistry.fill(HIST("Vertex/hNContrib"), collision.numContrib()); |
| 145 | + fRegistry.fill(HIST("Vertex/hChi2"), collision.chi2() / collision.numContrib()); |
| 146 | + fRegistry.fill(HIST("Vertex/hChi2vsNContrib"), collision.numContrib(), collision.chi2() / collision.numContrib()); |
| 147 | + |
| 148 | + fRegistry.fill(HIST("Vertex/hSigmaX"), collision.numContrib(), std::sqrt(collision.covXX()) * 1e+4); // convert cm to um |
| 149 | + fRegistry.fill(HIST("Vertex/hSigmaY"), collision.numContrib(), std::sqrt(collision.covYY()) * 1e+4); // convert cm to um |
| 150 | + fRegistry.fill(HIST("Vertex/hSigmaZ"), collision.numContrib(), std::sqrt(collision.covZZ()) * 1e+4); // convert cm to um |
| 151 | + |
| 152 | + fRegistry.fill(HIST("Vertex/hDeltaX"), collision.numContrib(), (collision.posX() - mcCollision.posX()) / std::sqrt(collision.covXX())); |
| 153 | + fRegistry.fill(HIST("Vertex/hDeltaY"), collision.numContrib(), (collision.posY() - mcCollision.posY()) / std::sqrt(collision.covYY())); |
| 154 | + fRegistry.fill(HIST("Vertex/hDeltaZ"), collision.numContrib(), (collision.posZ() - mcCollision.posZ()) / std::sqrt(collision.covZZ())); |
| 155 | + |
| 156 | + fRegistry.fill(HIST("Vertex/hCollisionTime"), collision.numContrib(), collision.collisionTime()); |
| 157 | + fRegistry.fill(HIST("Vertex/hCollisionTimeRes"), collision.numContrib(), collision.collisionTimeRes()); |
| 158 | + } |
| 159 | + |
| 160 | + template <typename TBCs, typename TCollisions, typename TMCCollisions, typename TMCParticles> |
| 161 | + void run(TBCs const&, TCollisions const& collisions, TMCCollisions const&, TMCParticles const&) |
| 162 | + { |
| 163 | + for (const auto& collision : collisions) { |
| 164 | + if (!collision.has_mcCollision()) { |
| 165 | + continue; |
| 166 | + } |
| 167 | + auto bc = collision.template bc_as<TBCs>(); |
| 168 | + initCCDB(bc); |
| 169 | + |
| 170 | + auto mcCollision = collision.template mcCollision_as<aod::McCollisions>(); |
| 171 | + if (eventCut.cfgEventGeneratorId > -1 && mcCollision.getSubGeneratorId() != eventCut.cfgEventGeneratorId) { |
| 172 | + continue; |
| 173 | + } |
| 174 | + |
| 175 | + fRegistry.fill(HIST("hCollisionCounter"), 1); |
| 176 | + |
| 177 | + if (!isSelectedCollision(collision)) { |
| 178 | + continue; |
| 179 | + } |
| 180 | + fRegistry.fill(HIST("hCollisionCounter"), 2); |
| 181 | + |
| 182 | + fillVertexHistograms(collision, mcCollision); |
| 183 | + |
| 184 | + } // end of collision loop |
| 185 | + } |
| 186 | + |
| 187 | + using MyCollisions = soa::Join<aod::Collisions, aod::EvSels, aod::McCollisionLabels>; |
| 188 | + using MyBCs = soa::Join<aod::BCsWithTimestamps, aod::BcSels>; |
| 189 | + |
| 190 | + Filter collisionFilter_evsel = eventCut.cfgZvtxMin < o2::aod::collision::posZ && o2::aod::collision::posZ < eventCut.cfgZvtxMax; |
| 191 | + using FilteredMyCollisions = soa::Filtered<MyCollisions>; |
| 192 | + |
| 193 | + void processMC(FilteredMyCollisions const& collisions, MyBCs const& bcs, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) |
| 194 | + { |
| 195 | + run(bcs, collisions, mcCollisions, mcParticles); |
| 196 | + } |
| 197 | + PROCESS_SWITCH(testPV, processMC, "processMC", true); |
| 198 | + |
| 199 | + void processDummy(MyCollisions const&) {} |
| 200 | + PROCESS_SWITCH(testPV, processDummy, "processDummy", false); |
| 201 | +}; |
| 202 | +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) |
| 203 | +{ |
| 204 | + return WorkflowSpec{adaptAnalysisTask<testPV>(cfgc, TaskName{"test-pv"})}; |
| 205 | +} |
0 commit comments