|
| 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 | +#include <vector> |
| 13 | + |
| 14 | +#include "Framework/runDataProcessing.h" |
| 15 | +#include "Framework/AnalysisTask.h" |
| 16 | +#include "Framework/AnalysisDataModel.h" |
| 17 | +#include "Framework/ASoAHelpers.h" |
| 18 | +#include "ReconstructionDataFormats/Track.h" |
| 19 | +#include "Common/Core/RecoDecay.h" |
| 20 | +#include "Common/Core/trackUtilities.h" |
| 21 | +#include "Common/DataModel/EventSelection.h" |
| 22 | +#include "PWGLF/DataModel/LFStrangenessTables.h" |
| 23 | +#include "DetectorsBase/Propagator.h" |
| 24 | +#include "DetectorsBase/GeometryManager.h" |
| 25 | +#include "DataFormatsParameters/GRPObject.h" |
| 26 | +#include "DataFormatsParameters/GRPMagField.h" |
| 27 | +#include "CCDB/BasicCCDBManager.h" |
| 28 | + |
| 29 | +#include "Common/Core/PID/TPCPIDResponse.h" |
| 30 | +#include "Common/DataModel/PIDResponse.h" |
| 31 | + |
| 32 | +#include "TDatabasePDG.h" |
| 33 | + |
| 34 | +using namespace o2; |
| 35 | +using namespace o2::framework; |
| 36 | +using namespace o2::framework::expressions; |
| 37 | + |
| 38 | +using TracksFull = soa::Join<aod::TracksIU, aod::TracksExtra, aod::TracksCovIU, aod::pidTPCDe, aod::pidTPCPr, aod::pidTPCPi, aod::pidTOFDe>; |
| 39 | + |
| 40 | +namespace |
| 41 | +{ |
| 42 | +const float lambdaMassPDG = TDatabasePDG::Instance()->GetParticle(3122)->Mass(); |
| 43 | +} |
| 44 | + |
| 45 | +struct antidLambdaEbye { |
| 46 | + Service<o2::ccdb::BasicCCDBManager> ccdb; |
| 47 | + |
| 48 | + Configurable<int> cfgMaterialCorrection{"cfgMaterialCorrection", static_cast<int>(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction"}; |
| 49 | + |
| 50 | + ConfigurableAxis zVtxAxis{"zVtxBins", {100, -20.f, 20.f}, "Binning for the vertex z in cm"}; |
| 51 | + ConfigurableAxis massLambdaAxis{"massLambdaAxis", {400, lambdaMassPDG - 0.03f, lambdaMassPDG + 0.03f}, "binning for the lambda invariant-mass"}; |
| 52 | + ConfigurableAxis centAxis{"centAxis", {106, 0, 106}, "binning for the centrality"}; |
| 53 | + |
| 54 | + ConfigurableAxis cosPaAxis{"cosPaAxis", {1e3, 0.95f, 1.00f}, "binning for the cosPa axis"}; |
| 55 | + ConfigurableAxis radiusAxis{"radiusAxis", {1e3, 0.f, 100.f}, "binning for the radius axis"}; |
| 56 | + ConfigurableAxis dcaV0daughAxis{"dcaV0daughAxis", {2e2, 0.f, 2.f}, "binning for the dca of V0 daughters"}; |
| 57 | + ConfigurableAxis dcaDaughPvAxis{"dcaDaughPvAxis", {1e3, 0.f, 10.f}, "binning for the dca of positive daughter to PV"}; |
| 58 | + |
| 59 | + ConfigurableAxis tpcNsigmaAxis{"tpcNsigmaAxis", {100, -5.f, 5.f}, "tpc nsigma axis"}; |
| 60 | + ConfigurableAxis tofNsigmaAxis{"tofNsigmaAxis", {100, -5.f, 5.f}, "tof nsigma axis"}; |
| 61 | + |
| 62 | + // CCDB options |
| 63 | + Configurable<double> d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; |
| 64 | + Configurable<std::string> ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; |
| 65 | + Configurable<std::string> grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; |
| 66 | + Configurable<std::string> grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; |
| 67 | + Configurable<std::string> lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; |
| 68 | + Configurable<std::string> geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; |
| 69 | + Configurable<std::string> pidPath{"pidPath", "", "Path to the PID response object"}; |
| 70 | + |
| 71 | + Configurable<float> zVtxMax{"zVtxMax", 10.0f, "maximum z position of the primary vertex"}; |
| 72 | + Configurable<float> etaMax{"etaMax", 0.8f, "maximum eta"}; |
| 73 | + |
| 74 | + Configurable<float> antidPtMin{"antidPtMin", 0.8f, "minimum antideuteron pT (GeV/c)"}; |
| 75 | + Configurable<float> antidPtTof{"antidPtTof", 1.0f, "antideuteron pT to switch to TOF pid (GeV/c) "}; |
| 76 | + Configurable<float> antidPtMax{"antidPtMax", 1.8f, "maximum antideuteron pT (GeV/c)"}; |
| 77 | + |
| 78 | + Configurable<float> lambdaPtMin{"lambdaPtMin", 0.5f, "minimum (anti)lambda pT (GeV/c)"}; |
| 79 | + Configurable<float> lambdaPtMax{"lambdaPtMax", 3.0f, "maximum (anti)lambda pT (GeV/c)"}; |
| 80 | + |
| 81 | + Configurable<float> antidNclusItsCut{"antidNclusITScut", 5, "Minimum number of ITS clusters"}; |
| 82 | + Configurable<float> antidNclusTpcCut{"antidNclusTPCcut", 70, "Minimum number of TPC clusters"}; |
| 83 | + Configurable<float> antidNsigmaTpcCut{"antidNsigmaTpcCut", 4.f, "TPC PID cut"}; |
| 84 | + Configurable<float> antidNsigmaTofCut{"antidNsigmaTofCut", 4.f, "TOF PID cut"}; |
| 85 | + Configurable<float> antidDcaCut{"antidDcaCut", 0.1f, "DCA antid to PV"}; |
| 86 | + |
| 87 | + Configurable<float> v0setting_dcav0dau{"v0setting_dcav0dau", 1, "DCA V0 Daughters"}; |
| 88 | + Configurable<float> v0setting_dcapostopv{"v0setting_dcapostopv", 0.1f, "DCA Pos To PV"}; |
| 89 | + Configurable<float> v0setting_dcanegtopv{"v0setting_dcanegtopv", 0.1f, "DCA Neg To PV"}; |
| 90 | + Configurable<double> v0setting_cospa{"v0setting_cospa", 0.98, "V0 CosPA"}; |
| 91 | + Configurable<float> v0setting_radius{"v0setting_radius", 0.5f, "v0radius"}; |
| 92 | + Configurable<float> lambdaMassCut{"lambdaMassCut", 0.005f, "maximum deviation from PDG mass"}; |
| 93 | + |
| 94 | + int mRunNumber; |
| 95 | + float d_bz; |
| 96 | + |
| 97 | + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; |
| 98 | + |
| 99 | + Filter preFilterV0 = (nabs(aod::v0data::dcapostopv) > v0setting_dcapostopv && |
| 100 | + nabs(aod::v0data::dcanegtopv) > v0setting_dcanegtopv && |
| 101 | + aod::v0data::dcaV0daughters < v0setting_dcav0dau); |
| 102 | + |
| 103 | + template <class RecV0> |
| 104 | + bool selectLambda(RecV0 const& v0) // TODO: apply ML |
| 105 | + { |
| 106 | + if (std::abs(v0.eta()) > etaMax || |
| 107 | + v0.v0cosPA() < v0setting_cospa || |
| 108 | + v0.v0radius() < v0setting_radius) { |
| 109 | + return false; |
| 110 | + } |
| 111 | + auto mLambda = v0.alpha() > 0 ? v0.mLambda() : v0.mAntiLambda(); |
| 112 | + if (std::abs(mLambda - lambdaMassPDG) > lambdaMassCut) { |
| 113 | + return false; |
| 114 | + } |
| 115 | + return true; |
| 116 | + } |
| 117 | + |
| 118 | + template <class T> |
| 119 | + bool selectAntid(T const& track) |
| 120 | + { |
| 121 | + if (std::abs(track.eta()) > etaMax) { |
| 122 | + return false; |
| 123 | + } |
| 124 | + if (track.sign() > 0.) { |
| 125 | + return false; |
| 126 | + } |
| 127 | + if (track.itsNCls() < antidNclusItsCut || |
| 128 | + track.tpcNClsFound() < antidNclusTpcCut || |
| 129 | + track.tpcNClsCrossedRows() < 70 || |
| 130 | + track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable() || |
| 131 | + track.tpcChi2NCl() > 4.f || |
| 132 | + track.itsChi2NCl() > 36.f || |
| 133 | + !(track.trackType() & o2::aod::track::TPCrefit) || |
| 134 | + !(track.trackType() & o2::aod::track::ITSrefit)) { |
| 135 | + return false; |
| 136 | + } |
| 137 | + return true; |
| 138 | + } |
| 139 | + |
| 140 | + void init(o2::framework::InitContext&) |
| 141 | + { |
| 142 | + ccdb->setURL(ccdburl); |
| 143 | + ccdb->setCaching(true); |
| 144 | + ccdb->setLocalObjectValidityChecking(); |
| 145 | + ccdb->setFatalWhenNull(false); |
| 146 | + |
| 147 | + mRunNumber = 0; |
| 148 | + d_bz = 0; |
| 149 | + |
| 150 | + histos.add<TH1>("zVtx", ";#it{z}_{vtx} (cm);Entries", HistType::kTH1F, {zVtxAxis}); |
| 151 | + |
| 152 | + histos.add<TH1>("nEv", ";#it{N}_{ev};Entries", {HistType::kTH1D}, {centAxis}); |
| 153 | + |
| 154 | + histos.add<TH1>("q1antid", ";Centrality (%);#it{q}_{1}(#bar{d})", {HistType::kTH1D}, {centAxis}); |
| 155 | + histos.add<TH1>("q1sqantid", ";Centrality (%);#it{q}_{1}^{2}(#bar{d})", {HistType::kTH1D}, {centAxis}); |
| 156 | + histos.add<TH1>("q2antid", ";Centrality (%);#it{q}_{2}(#bar{d})", {HistType::kTH1D}, {centAxis}); |
| 157 | + |
| 158 | + histos.add<TH1>("q1antiL", ";Centrality (%);#it{q}_{1}(#bar{#Lambda})", {HistType::kTH1D}, {centAxis}); |
| 159 | + histos.add<TH1>("q1sqantiL", ";Centrality (%);#it{q}_{1}^{2}(#bar{#Lambda})", {HistType::kTH1D}, {centAxis}); |
| 160 | + histos.add<TH1>("q2antiL", ";Centrality (%);#it{q}_{2}(#bar{#Lambda})", {HistType::kTH1D}, {centAxis}); |
| 161 | + |
| 162 | + histos.add<TH1>("q1L", ";Centrality (%);#it{q}_{1}(#Lambda)", {HistType::kTH1D}, {centAxis}); |
| 163 | + histos.add<TH1>("q1sqL", ";Centrality (%);#it{q}_{1}^{2}(#Lambda)", {HistType::kTH1D}, {centAxis}); |
| 164 | + histos.add<TH1>("q2L", ";Centrality (%);#it{q}_{2}(#Lambda)", {HistType::kTH1D}, {centAxis}); |
| 165 | + |
| 166 | + histos.add<TH1>("q11Lantid", ";Centrality (%);#it{q}_{11}(#Lambda, #bar{d})", {HistType::kTH1D}, {centAxis}); |
| 167 | + histos.add<TH1>("q11antiLantid", ";Centrality (%);#it{q}_{11}(#bar{#Lambda}, #bar{d})", {HistType::kTH1D}, {centAxis}); |
| 168 | + |
| 169 | + // v0 QA |
| 170 | + histos.add<TH1>("massLambda", ";#it{M}(p + #pi^{-}) (GeV/#it{c}^{2});Entries", {HistType::kTH1F, {massLambdaAxis}}); |
| 171 | + histos.add<TH1>("cosPa", ";cosPa;Entries", {HistType::kTH1F}, {cosPaAxis}); |
| 172 | + histos.add<TH1>("radius", ";radius;Entries", {HistType::kTH1F}, {radiusAxis}); |
| 173 | + histos.add<TH1>("dcaV0daugh", ";dcaV0daugh;Entries", {HistType::kTH1F}, {dcaV0daughAxis}); |
| 174 | + histos.add<TH1>("dcaPosPv", ";dcaPosPv;Entries", {HistType::kTH1F}, {dcaDaughPvAxis}); |
| 175 | + histos.add<TH1>("dcaNegPv", ";dcaNegPv;Entries", {HistType::kTH1F}, {dcaDaughPvAxis}); |
| 176 | + |
| 177 | + // v0 QA |
| 178 | + histos.add<TH1>("tpcNsigma", ";tpcNsigma;Entries", {HistType::kTH1F, {tpcNsigmaAxis}}); |
| 179 | + histos.add<TH1>("tofNsigma", ";tofNsigma;Entries", {HistType::kTH1F}, {tofNsigmaAxis}); |
| 180 | + } |
| 181 | + |
| 182 | + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) |
| 183 | + { |
| 184 | + if (mRunNumber == bc.runNumber()) { |
| 185 | + return; |
| 186 | + } |
| 187 | + auto run3grp_timestamp = bc.timestamp(); |
| 188 | + |
| 189 | + o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp<o2::parameters::GRPObject>(grpPath, run3grp_timestamp); |
| 190 | + o2::parameters::GRPMagField* grpmag = 0x0; |
| 191 | + if (grpo) { |
| 192 | + o2::base::Propagator::initFieldFromGRP(grpo); |
| 193 | + if (d_bz_input < -990) { |
| 194 | + // Fetch magnetic field from ccdb for current collision |
| 195 | + d_bz = grpo->getNominalL3Field(); |
| 196 | + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; |
| 197 | + } else { |
| 198 | + d_bz = d_bz_input; |
| 199 | + } |
| 200 | + } else { |
| 201 | + grpmag = ccdb->getForTimeStamp<o2::parameters::GRPMagField>(grpmagPath, run3grp_timestamp); |
| 202 | + if (!grpmag) { |
| 203 | + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; |
| 204 | + } |
| 205 | + o2::base::Propagator::initFieldFromGRP(grpmag); |
| 206 | + if (d_bz_input < -990) { |
| 207 | + // Fetch magnetic field from ccdb for current collision |
| 208 | + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); |
| 209 | + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; |
| 210 | + } else { |
| 211 | + d_bz = d_bz_input; |
| 212 | + } |
| 213 | + } |
| 214 | + mRunNumber = bc.runNumber(); |
| 215 | + } |
| 216 | + |
| 217 | + void process(soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Cs>::iterator const& collision, TracksFull const& tracks, soa::Filtered<aod::V0Datas> const& V0s, aod::BCsWithTimestamps const&) |
| 218 | + { |
| 219 | + auto bc = collision.bc_as<aod::BCsWithTimestamps>(); |
| 220 | + initCCDB(bc); |
| 221 | + |
| 222 | + if (!collision.sel8()) |
| 223 | + return; |
| 224 | + |
| 225 | + if (std::abs(collision.posZ()) > zVtxMax) |
| 226 | + return; |
| 227 | + |
| 228 | + const o2::math_utils::Point3D<float> collVtx{collision.posX(), collision.posY(), collision.posZ()}; |
| 229 | + |
| 230 | + histos.fill(HIST("zVtx"), collision.posZ()); |
| 231 | + |
| 232 | + double q1antid{0.}, q2antid{0.}; |
| 233 | + for (const auto& track : tracks) { |
| 234 | + if (!selectAntid(track)) { |
| 235 | + continue; |
| 236 | + } |
| 237 | + |
| 238 | + auto trackParCov = getTrackParCov(track); |
| 239 | + gpu::gpustd::array<float, 2> dcaInfo; |
| 240 | + o2::base::Propagator::Instance()->propagateToDCABxByBz(collVtx, trackParCov, 2.f, static_cast<o2::base::Propagator::MatCorrType>(cfgMaterialCorrection.value), &dcaInfo); |
| 241 | + |
| 242 | + float dcaXYZ = dcaInfo[0]; |
| 243 | + if (std::abs(dcaXYZ) > antidDcaCut) { |
| 244 | + continue; |
| 245 | + } |
| 246 | + |
| 247 | + if (trackParCov.getPt() < antidPtMin || trackParCov.getPt() > antidPtMax) { |
| 248 | + continue; |
| 249 | + } |
| 250 | + if (std::abs(track.tpcNSigmaDe()) > antidNsigmaTpcCut) { |
| 251 | + continue; |
| 252 | + } |
| 253 | + if (std::abs(track.tofNSigmaDe()) > antidNsigmaTofCut && trackParCov.getPt() > antidPtTof) { |
| 254 | + continue; |
| 255 | + } |
| 256 | + |
| 257 | + histos.fill(HIST("tpcNsigma"), track.tpcNSigmaDe()); |
| 258 | + if (trackParCov.getPt() > antidPtTof) { |
| 259 | + histos.fill(HIST("tofNsigma"), track.tofNSigmaDe()); |
| 260 | + } |
| 261 | + |
| 262 | + q1antid += 1.; // TODO: correct for efficiency |
| 263 | + q2antid += 1.; |
| 264 | + } |
| 265 | + |
| 266 | + double q1L{0.}, q2L{0.}, q1antiL{0.}, q2antiL{0.}; |
| 267 | + std::vector<int64_t> trkId; |
| 268 | + for (const auto& v0 : V0s) { |
| 269 | + if (v0.pt() < lambdaPtMin || v0.pt() > lambdaPtMax) { |
| 270 | + continue; |
| 271 | + } |
| 272 | + |
| 273 | + if (!selectLambda(v0)) { |
| 274 | + continue; |
| 275 | + } |
| 276 | + |
| 277 | + auto pos = v0.template posTrack_as<TracksFull>(); |
| 278 | + auto neg = v0.template negTrack_as<TracksFull>(); |
| 279 | + if (std::abs(pos.eta()) > etaMax || std::abs(pos.eta()) > etaMax) { |
| 280 | + continue; |
| 281 | + } |
| 282 | + |
| 283 | + bool matter = v0.alpha() > 0; |
| 284 | + |
| 285 | + histos.fill(HIST("massLambda"), matter ? v0.mLambda() : v0.mAntiLambda()); |
| 286 | + histos.fill(HIST("cosPa"), v0.v0cosPA()); |
| 287 | + histos.fill(HIST("radius"), v0.v0radius()); |
| 288 | + histos.fill(HIST("dcaV0daugh"), v0.dcaV0daughters()); |
| 289 | + histos.fill(HIST("dcaPosPv"), v0.dcapostopv()); |
| 290 | + histos.fill(HIST("dcaNegPv"), v0.dcanegtopv()); |
| 291 | + |
| 292 | + if (matter) { |
| 293 | + q1L += 1.; // TODO: correct for efficiency |
| 294 | + q2L += 1.; |
| 295 | + } else { |
| 296 | + q1antiL += 1.; // TODO: correct for efficiency |
| 297 | + q2antiL += 1.; |
| 298 | + } |
| 299 | + |
| 300 | + trkId.emplace_back(pos.globalIndex()); |
| 301 | + trkId.emplace_back(neg.globalIndex()); |
| 302 | + } |
| 303 | + |
| 304 | + // reject events having multiple v0s from same tracks (TODO: also across collisions?) |
| 305 | + std::sort(trkId.begin(), trkId.end()); |
| 306 | + if (std::adjacent_find(trkId.begin(), trkId.end()) != trkId.end()) { |
| 307 | + return; |
| 308 | + } |
| 309 | + |
| 310 | + histos.fill(HIST("nEv"), collision.centFT0C()); |
| 311 | + |
| 312 | + histos.fill(HIST("q1antid"), collision.centFT0C(), q1antid); |
| 313 | + histos.fill(HIST("q1sqantid"), collision.centFT0C(), std::pow(q1antid, 2)); |
| 314 | + histos.fill(HIST("q2antid"), collision.centFT0C(), q2antid); |
| 315 | + |
| 316 | + histos.fill(HIST("q1L"), collision.centFT0C(), q1L); |
| 317 | + histos.fill(HIST("q1sqL"), collision.centFT0C(), std::pow(q1L, 2)); |
| 318 | + histos.fill(HIST("q2L"), collision.centFT0C(), q2L); |
| 319 | + |
| 320 | + histos.fill(HIST("q1antiL"), collision.centFT0C(), q1antiL); |
| 321 | + histos.fill(HIST("q1sqantiL"), collision.centFT0C(), std::pow(q1antiL, 2)); |
| 322 | + histos.fill(HIST("q2antiL"), collision.centFT0C(), q2antiL); |
| 323 | + |
| 324 | + histos.fill(HIST("q11Lantid"), collision.centFT0C(), q1L * q1antid); |
| 325 | + histos.fill(HIST("q11antiLantid"), collision.centFT0C(), q1antiL * q1antid); |
| 326 | + } |
| 327 | +}; |
| 328 | + |
| 329 | +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) |
| 330 | +{ |
| 331 | + return WorkflowSpec{ |
| 332 | + adaptAnalysisTask<antidLambdaEbye>(cfgc)}; |
| 333 | +} |
0 commit comments